Есть ли способ деструктурировать параметр функции и сохранить именованную ссылку на параметр?

В реагирующих функциональных компонентах без состояния мы обычно пишем что-то вроде этого:

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>
}

Довольно придирчивый, я знаю, просто интересно.

хороший вопрос, я бы сделал это так, как вы это сделали, поэтому мне будет интересно увидеть здесь другие ответы.

ak85 29.05.2019 05:29
stackoverflow.com/questions/29051011/…
Bergi 05.02.2022 03:47
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
14
2
3 807
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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 будет содержать именно те данные, с которыми была вызвана функция. По этой причине, вероятно, лучше всего принять один параметр, а затем деструктурировать его позже.

fregante 26.09.2021 18:11

Другие вопросы по теме