В настоящее время я создаю компонент 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
Таким образом, я думаю, что мой код будет настолько чистым, насколько это возможно. Спасибо.
«Некоторый код для деструктуризации всех реквизитов в отдельные переменные» будет простой деструктуризацией:
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 thecomp1Props
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
имен или их количества. Является ли это возможным?
@ cbdev420 - А, это совсем другой вопрос. Как узнать, какие свойства вставить в comp1Props
и какие вставить comp2Props
?
Я все равно решу это и создам эти объекты вручную. Но если передать новый prop
в AddProductPage
, я бы хотел, чтобы он автоматически деструктурировался и был доступен для добавления, например, в объект comp1Props
. В противном случае мне пришлось бы не забыть сначала деструктурировать его, а затем добавить к объекту comp1Props
.
Возможно, используя Object.entries()
. Я не знаю.
@ cbdev420 - я обновил ответ. Это правда, что вы могли бы использовать Object.entries
(хорошая мысль!) и еще более новый Object.fromEntries
с вызовом filter
, но, честно говоря, это некрасиво и не особенно эффективно: const comp1Props = Object.fromEntries(Object.entries(props).filter(([name]) => name === "propA" || name === "propB"));
Согласованный! Большое спасибо!
@cbdev420 - К сожалению, это предложение по синтаксису выбора, похоже, не находит чемпиона TC39. Это то, что вы хотите. :-)
Не уверен, с каких пор, но теперь при деструктуризации требуется добавить значение по умолчанию.
@CarmineTambascia - для деструктуризации не требуется значение по умолчанию. Вы просто получите сообщение об ошибке, если попытаетесь деструктурировать undefined
(точно так же, как const { foo } = undefined;
. Вы это имеете в виду?
Да, вы правы, я неправильно выразился, прошу прощения. Я действительно получил эту ошибку, потому что в родительском компоненте я ссылался только на переменную вместо массива.
вы можете сделать что-то вроде
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
имен или их количества. Является ли это возможным?
Затем передайте все реквизиты напрямую.
Вы можете использовать:
function AddProductPage({propsA, propsB, propsC, propsD, propsE}) {
Или
const {propsA, propsB, propsC, propsD, propsE} = props
Спасибо! Думаю, я недостаточно ясно выразился в своем вопросе. Но под динамическим я имел в виду деструктурировать все, не зная имен реквизитов или их количества. Является ли это возможным?
Я немного опоздал на вечеринку, но я хотел бы упомянуть, как сделать ваш код читабельным и, следовательно, удобным для сопровождения. Вы должны отделить свой код и, таким образом, разделить свои проблемы.
Лично я думаю, что вы думаете, что слишком много для того, что вам нужно. Для каждого 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
отвечает за рендеринг компонентов пользовательского интерфейса страницы, каждый из которых имеет свои реквизиты.
Итак, я условно визуализирую 8 компонентов, например, в зависимости от статуса loading
и error
. Таким образом, return
из AddProductPage
становилось слишком переполненным условиями и компонентами по 4 или 5 props
в каждом. Было трудно понять, что рендерится при каждом state
условии. Именно тогда я начал искать другое место, чтобы «организовать» props
для каждого компонента. И вызывайте каждый из них одним prop
объектом.
Если я деструктурирую их все в объявлении функции компонента, как вы сделали в своем последнем примере, если я создам новый prop
в моем ContainerComponent
, мне придется не забыть добавить его в двух местах в моем PageComponent
вместо одного. Вот почему я искал способ деструктурировать их все динамически. Большое спасибо за ваше время и усилия.
Ответы могут помочь вам заработать деньги, так как я не верю, что
propsA
,propsB
и т. д. — это реквизит, на который вы хотите пойти, но они соответствуют вашему вопросу :)