В реагирующих функциональных компонентах без состояния мы обычно пишем что-то вроде этого:
export function MyCompoment({
title,
foo,
bar
}) {
return <div> title: {title}, ...</div>
}
Где мы немедленно деструктурируем объект реквизита в его переменные.
Теперь я использую хук Material-UI makeStyles
, а также TypeScript, и то, как я его сейчас использую, выглядит так.
const useStyles = makeStyles((theme : Theme ) =>({
root: ({foo} : MyComponentProps) => ({
content: foo
})
});
interface MyComponentProps {
title: string;
foo: string;
bar: string;
}
export function MyCompoment({
title,
foo,
bar
} : MyComponentProps) {
const classes = useStyles({
title,
foo,
bar
});
return <div> title: {title}, ...</div>
}
И вы можете видеть проблему — я должен повторять имена переменных props, чтобы передать их в классы.
Лучший способ избежать этого - написать так:
export function MyCompoment(props: MyComponentProps) {
const {
title,
foo,
bar
} = props;
const classes = useStyles(props);
return <div> title: {title}, ...</div>
}
Но это немного грязнее, чем я хотел.
Мне было интересно, можно ли сделать что-то вроде:
export function MyCompoment({
title,
foo,
bar
} = props : MyComponentProps) {
const classes = useStyles(props);
return <div> title: {title}, ...</div>
}
Довольно придирчивый, я знаю, просто интересно.
Is there a way to both destructure a function parameter, and keep a named reference to the parameter?
Нет. Вам нужно будет сделать это в два этапа, так как вы берете реквизиты в качестве одного аргумента, а затем деструктурируете их позже.
Нет (в основном)
Трудно доказать отрицание, поэтому мне пришлось обратиться к грамматике.
Typescript, насколько мне известно, не обеспечивает никакой дополнительной деструктурирующей способности, которой нет у javascript, поэтому я просто отвечу на этот вопрос для javascript.
В грамматике ES6 нет возможности одновременно уничтожить один параметр функции и присвоить ему имя в списке параметров в одном параметре.
Если вы посмотрите на Грамматика ES6 для FormalParameter
, который является одним из элементов в списке аргументов, вы обнаружите, что это может быть только BindingElement
, то есть либо SingleNameBinding
, либо BindingPattern
, а не то и другое одновременно. Шаблоны привязки могут выполнять только деструктурирование, а привязки одного имени могут назначаться только одному значению, поэтому нет возможности сделать и то, и другое.
(Обратите внимание, что грамматика, на которую я ссылаюсь, - это всего лишь суть, которую кто-то разместил на github. Я не думаю, что кто-то опубликует вводящую в заблуждение грамматику ES6 на github, но если вы настроены скептически, вы всегда можете проверить менее удобную официальную грамматику.)
Возможно, есть какой-то другой дикий способ сделать это, который я пропустил, но я никогда не видел его раньше и был бы очень удивлен.
Ты "лучший способ, о котором ты можешь думать" - это лучший способ, о котором я тоже могу думать. Вы должны сделать это.
Однако я не люблю отвечать «нет», поэтому, если вы действительно хотите получить все это в списке параметров, вы можете вместо этого сделать что-то неприятное. Если вы сделаете:
function assignAndDestructure(props, { foo, bar } = props) {
// props, foo, and bar will all be assigned
}
какой вид соответствует вашим критериям. Однако он создает необязательный второй параметр, которым вызывающая сторона может злоупотреблять, чтобы испортить вашу деструктуризацию. Вы можете скрыть его, назначив его типу, у которого нет этого параметра в Typescript, но это все равно рискованно.
В общем, нет хорошего способа сделать это, но есть плохой способ. Идите с упомянутым вами «лучшее, что вы можете придумать».
Я не понимаю, почему кто-то придумал этот ответ...
У вас всегда есть ссылка на параметр в arguments
.
function _test({ a, b }){
var arg = arguments[0];
console.info("a = ",a,"b = ",b,"arg = ",arg);
}
При тестировании выдает этот вывод:
_test({ a:23, b:"asd", c:"$" })
// a= 23 b= asd arg= { a: 23, b: 'asd', c: '$' }
В вашем случае это можно сделать так.
export function MyCompoment({
title,
foo,
bar
}) {
const props = arguments[0];
const classes = useStyles(props);
return <div> title: {title}, ...</div>
}
Это правильный ответ. arguments
— это ссылка, которую вы ищете. Однако не применяет никаких значений по умолчанию, arguments
будет содержать именно те данные, с которыми была вызвана функция. По этой причине, вероятно, лучше всего принять один параметр, а затем деструктурировать его позже.
хороший вопрос, я бы сделал это так, как вы это сделали, поэтому мне будет интересно увидеть здесь другие ответы.