Динамическое разрушение реквизита?

В настоящее время я создаю компонент AddProductPage для своего веб-приложения. Он получает кучу props от своего родителя AddProductContainer и должен разделить эти props между множеством более мелких компонентов, которые он отображает на странице.

Пример:

AddProductPage.js

function AddProductPage(props) {

  return(
    <React.Fragment>
      <Component1
        propsA = {props.propsA}
        propsB = {props.propsB}
      />
      <Component2
        propsC = {props.propsC}
        propsD = {props.propsD}
        propsE = {props.propsE}
      />
      // And so on...
    </React.Fragment>
  );
}

Я решил разделить полный объект props на более мелкие объекты, по одному для каждого компонента, чтобы я мог видеть, что мой код будет отображать на странице в более четком виде. Нравиться:

function AddProductPage(props) {

  const comp1Props = {
    propsA: props.propsA,
    propsB: props.propsB
  }

  const comp2Props = {
    propsC: props.propsC,
    propsD: props.propsD,
    propsE: props.propsE
  }

  return(
    <React.Fragment>
      <Component1 {...comp1Props}/>    // <--- Easier to see what will render
      <Component2 {...comp2Porps}/>
      // And so on...
    </React.Fragment>
  );
}

В настоящее время я думаю, возможно ли динамически деструктурировать (или какой-либо другой подход) все props в отдельные переменные, чтобы я мог написать что-то вроде этого:

function AddProductPage(props) {

  // Some code to destructure all props into single variables

  const comp1Props = {
    propsA,
    propsB
  };

  const comp2Props = {
    propsC,
    propsD,
    propsE
  };

  return(
    <React.Fragment>
      <Component1 {...comp1Props}/>    // <--- Easier to see what will render
      <Component2 {...comp2Porps}/>
      // And so on...
    </React.Fragment>
  );

}

Как я могу это сделать?

РЕДАКТИРОВАТЬ

Думаю, я недостаточно ясно выразился в своем вопросе. Но под динамическим я имел в виду деструктурировать все, не зная props имен или их количества. Является ли это возможным?

Нравиться:

props

Таким образом, я думаю, что мой код будет настолько чистым, насколько это возможно. Спасибо.

Ответы могут помочь вам заработать деньги, так как я не верю, что propsA, propsB и т. д. — это реквизит, на который вы хотите пойти, но они соответствуют вашему вопросу :)

Icepickle 08.04.2019 12:29
Поведение ключевого слова "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) для оценки ваших знаний,...
1
1
7 047
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

«Некоторый код для деструктуризации всех реквизитов в отдельные переменные» будет простой деструктуризацией:

const { propsA, propsB, propsC, propsD, propsE } = props;

Живой пример:

const props = {
    propsA: "a",
    propsB: "b",
    propsC: "c",
    propsD: "d",
    propsE: "e"
};

const { propsA, propsB, propsC, propsD, propsE } = props;

const comp1Props = {
    propsA,
    propsB
};

const comp2Props = {
    propsC,
    propsD,
    propsE
};

console.info(comp1Props);
console.info(comp2Props);
.as-console-wrapper {
  max-height: 100% !important;
}

В комментариях вы уточнили:

what I meant with dynamically is to destructure everything without knowing the props names or how many props there are.

Я спросил, как вы узнаете, что назначить comp1Props против comp2Props, и вы сказали:

I woud still decide that and create those objects manually. But if a pass a new prop to AddProductPage, I would like it to be automatically destructured and available to add that into the comp1Props object, for example. Otherwise I would have to remember to destructure it first and then add it to the comp1Props object.

Итак, вопрос: можете ли вы автоматически создавать константы/переменные для всех свойств props в AddProductPage, чтобы все они были доступны для использования в коде, создающем comp1Props и comp2Props?

Нет, вы не можете сделать это, не используя запутанную функцию (with), которая недоступна в строгом режиме (который включен по умолчанию в модулях). Если бы вы могли использовать with, вы бы просто сделали with (props) { /*...*/ } и создали свои comp1Props и comp2Props в этом блоке. Но вы не можете использовать with в современном JavaScript.

Вероятно, вам лучше всего делать то, что вы уже делаете:

const comp1Props = {
    propsA: props.propsA,
    propsB: props.propsB
};

Но если вы хотите сделать его короче, вы можете создать повторно используемую служебную функцию:

function pick(source, ...props) {
    const result = {};
    for (const prop of props) {
        result[prop] = source[prop];
    }
}

а затем используйте его в AddProductPage:

function AddProductPage(props) {
  const comp1Props = pick(props, "propsA", "propsB");
  const comp2Props = pick(props, "propsC", "propsD", "propsE");

  return(
    <React.Fragment>
      <Component1 {...comp1Props}/>
      <Component2 {...comp2Porps}/>
      // And so on...
    </React.Fragment>
  );
}

(Некоторые впихнули бы это в звонок reduce, но в этом нет необходимости.)

Спасибо! Думаю, я недостаточно ясно выразился в своем вопросе. Но под динамическим я имел в виду деструктурировать все, не зная props имен или их количества. Является ли это возможным?

cbdeveloper 08.04.2019 12:39

@ cbdev420 - А, это совсем другой вопрос. Как узнать, какие свойства вставить в comp1Props и какие вставить comp2Props?

T.J. Crowder 08.04.2019 12:40

Я все равно решу это и создам эти объекты вручную. Но если передать новый prop в AddProductPage, я бы хотел, чтобы он автоматически деструктурировался и был доступен для добавления, например, в объект comp1Props. В противном случае мне пришлось бы не забыть сначала деструктурировать его, а затем добавить к объекту comp1Props.

cbdeveloper 08.04.2019 12:44

Возможно, используя Object.entries(). Я не знаю.

cbdeveloper 08.04.2019 12:46

@ cbdev420 - я обновил ответ. Это правда, что вы могли бы использовать Object.entries (хорошая мысль!) и еще более новый Object.fromEntries с вызовом filter, но, честно говоря, это некрасиво и не особенно эффективно: const comp1Props = Object.fromEntries(Object.entries(props).filter(([name]) => name === "propA" || name === "propB"));

T.J. Crowder 08.04.2019 12:57

Согласованный! Большое спасибо!

cbdeveloper 08.04.2019 12:58

@cbdev420 - К сожалению, это предложение по синтаксису выбора, похоже, не находит чемпиона TC39. Это то, что вы хотите. :-)

T.J. Crowder 08.04.2019 13:02

Не уверен, с каких пор, но теперь при деструктуризации требуется добавить значение по умолчанию.

Carmine Tambascia 04.03.2020 15:26

@CarmineTambascia - для деструктуризации не требуется значение по умолчанию. Вы просто получите сообщение об ошибке, если попытаетесь деструктурировать undefined (точно так же, как const { foo } = undefined;. Вы это имеете в виду?

T.J. Crowder 04.03.2020 15:47

Да, вы правы, я неправильно выразился, прошу прощения. Я действительно получил эту ошибку, потому что в родительском компоненте я ссылался только на переменную вместо массива.

Carmine Tambascia 04.03.2020 15:49

вы можете сделать что-то вроде

function AddProductPage(props) {
    //Destructuring props and storing each keys in a sep varaiable  
    const { propsA, propsB, propsC, propsD, propsE } = props;   
    const comp1Props = {
        propsA,
        propsB
    };

    const comp2Props = {
        propsC,
        propsD,
        propsE
    };

    return(
        <React.Fragment>
            <Component1 {...comp1Props}/> 
            <Component2 {...comp2Porps}/>
            // And so on...
      </React.Fragment>
    );

}

Спасибо! Думаю, я недостаточно ясно выразился в своем вопросе. Но под динамическим я имел в виду деструктурировать все, не зная props имен или их количества. Является ли это возможным?

cbdeveloper 08.04.2019 12:39

Затем передайте все реквизиты напрямую.

Ashish 08.04.2019 12:43

Вы можете использовать:

function AddProductPage({propsA, propsB, propsC, propsD, propsE}) {

Или

const {propsA, propsB, propsC, propsD, propsE} = props

Спасибо! Думаю, я недостаточно ясно выразился в своем вопросе. Но под динамическим я имел в виду деструктурировать все, не зная имен реквизитов или их количества. Является ли это возможным?

cbdeveloper 08.04.2019 12:49

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

Лично я думаю, что вы думаете, что слишком много для того, что вам нужно. Для каждого Component1, Component2, Component3 и т. д. вы будете объявлять другое значение const, которое в зависимости от того, сколько у вас есть, будет влиять на производительность. Что еще более важно, у вас есть компонент и передаваемые реквизиты, как показано ниже (не встроенные в компонент), что делает его намного чище.

class MyComponentName extends Component {
  getComponentOne = () => {
    const { propsA, propsB } = this.props;

    //Any other logic for component 1 can go here.

    return (
      <Component1
        propsA = {propsA}
        propsB = {propsB}
      />
    );
  };

  getComponentTwo = () => {
    const { propsC, propsD, propsE} = this.props;

    //Any other logic for component 2 can go here.

    return (
      <Component2
        propsC = {propsC}
        propsD = {propsD}
        propsE = {propsE}
      />
    );
  };

  // Other component method getters

  addProductPage = () => (
    <React.Fragment>
      {this.getComponentOne()}
      {this.getComponentTwo()}
      // Get other component methods
    </React.Fragment>
  );

  render() {
    return(
      // Return whatever you wish here.
    );
  }
}

export default MyComponentName;

Две замечательные цитаты, над которыми стоит задуматься, принадлежат К. Мартину, который он написал в своей книге «Чистый код: руководство по Agile Software Craftsmanship»:

Even bad code can function. But if code isn’t clean, it can bring a development organization to its knees. Every year, countless hours and significant resources are lost because of poorly written code. But it doesn’t have to be that way.

А ТАКЖЕ

“Clean code is code that has been taken care of. Someone has taken the time to keep it simple and orderly. They have paid appropriate attention to details. They have cared.”

Также примечание относительно моего примера выше: я использую компоненты класса, так как не знаю, есть ли у вашего компонента какие-либо другие методы/логика. Как будто у вас есть другие методы в вашем функциональном компоненте, при каждом рендеринге эти методы будут повторно инициироваться, что опять же будет большой проблемой производительности.

Если у вас просто есть функциональный компонент и вы не хотите отделять свой код/не имеет логики и возвращает только JSX, то вы можете сделать это следующим образом.

const MyComponentName = ({
  propA,
  propB,
  propC,
  propD,
  propE,
  // Rest of props
}) => (
  <React.Fragment>
    <Component1
      propsA = {propsA}
      propsB = {propsB}
    />
    <Component2
      propsC = {propsC}
      propsD = {propsD}
      propsE = {propsE}
    />
    // Rest of you components (If simply returning JSX)
  </React.Fragment>
);

Надеюсь, вышеизложенное вам чем-то поможет.

Моя текущая схема дизайна для страницы AddProduct (каждая страница похожа на эту) в моем приложении выглядит следующим образом: у меня есть AddProductContainer, который обрабатывает вызовы API и содержит все state, необходимые для этой конкретной страницы. Этот компонент отображает AddProductPage с целой кучей реквизита. AddProductPage отвечает за рендеринг компонентов пользовательского интерфейса страницы, каждый из которых имеет свои реквизиты.

cbdeveloper 11.04.2019 11:24

Итак, я условно визуализирую 8 компонентов, например, в зависимости от статуса loading и error. Таким образом, return из AddProductPage становилось слишком переполненным условиями и компонентами по 4 или 5 props в каждом. Было трудно понять, что рендерится при каждом state условии. Именно тогда я начал искать другое место, чтобы «организовать» props для каждого компонента. И вызывайте каждый из них одним prop объектом.

cbdeveloper 11.04.2019 11:27

Если я деструктурирую их все в объявлении функции компонента, как вы сделали в своем последнем примере, если я создам новый prop в моем ContainerComponent, мне придется не забыть добавить его в двух местах в моем PageComponent вместо одного. Вот почему я искал способ деструктурировать их все динамически. Большое спасибо за ваше время и усилия.

cbdeveloper 11.04.2019 11:32

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