#javascript #reactjs #components #mapping #children
Вопрос:
Я пытаюсь реорганизовать свой код, и при этом я извлекаю один элемент и помещаю его в его собственный компонент. Этот MemberItem
компонент имеет состояние нескольких функций, которые влияют на его визуализацию, однако, когда я начинаю передавать реквизиты, компонент прерывается. Я передаю все функции, свойства и состояние, необходимые дочернему компоненту, но я все еще не могу заставить его правильно отображаться.
// Members.js (Parent Component)
export const Members = () => {
// BELOW ARE THE FUNCTIONS AND STATE THAT INFLUENCE THE CHILD COMPONENT
const [memberName, setMemberName] = useState('')
const [editingMemberName, setEditingMemberName] = useState(
members.map(() => false)
)
// Update member name
const editMemberName = async (_, index) => {
let new_editing_members_state = members.map(() => false)
new_editing_members_state[index] = true
setEditingMemberName(new_editing_members_state)
}
// Cancel editing mode
const cancelEditMemberName = async (_, index) => {
let new_editing_members_state = members.map(() => false)
new_editing_members_state[index] = false
setEditingMemberName(new_editing_members_state)
}
// UPDATE name in database
const updateMemberName = async (index, id) => {
let new_editing_members_state = members.map(() => false)
new_editing_members_state[index] = false
setEditingMemberName(new_editing_members_state)
}
// BELOW, LOOPS OVER EACH ITEM
const memberItems = members.map((member, index) => {
return (
<MemberItem
member={member}
index={index}
editingMemberName={editingMemberName[index]}
editMemberName={editMemberName}
handleChangeName={handleChangeName}
updateMemberName={updateMemberName}
cancelEditMemberName={cancelEditMemberName}
destroyMember={destroyMember}
/>
)
})
return (
// RENDER THE LIST OF ITEMS
{memberItems}
)
}
// Member.js (Child Component)
export const MemberItem = (
member,
index,
editingMemberName,
editMemberName,
handleChangeName,
updateMemberName,
cancelEditMemberName,
destroyMember
) => {
return (
<div
key={member.id}
>
<div>
{editingMemberName[index] ? (
<input
type="text"
placeholder="Johnny Appleseed"
onChange={handleChangeName}
/>
) : (
<>
<div>
{member.name.substring(0, 1).toUpperCase()}
</div>
<h3>{member.name}</h3>
</>
)}
</div>
<div>
{editingMemberName[index] ? (
<button
onClick={() => updateMemberName(index, member.id)}
>
<CgCheckO size=".75em" />
</button>
) : (
<button
onClick={() => editMemberName(member.id, index)}
>
<FiTool size=".75em" />
</button>
)}
<button>
{editingMemberName[index] ? (
<GiCancel
onClick={() => cancelEditMemberName(member.id, index)}
size=".75em"
/>
) : (
<RiDeleteBinLine
onClick={() => destroyMember(member.id)}
size=".75em"
/>
)}
</button>
</div>
</div>
)
}
В настоящее время я получаю сообщение об ошибке TypeError: editingMemberName is undefined
и предупреждение Each child in a list should have a unique "key" prop
, но , если вы видите, я передаю идентификатор в свойство ключа.
Комментарии:
1. То, что я сразу вижу , вы передаете
editingMemberName[index]
, следовательно, в дочернем компоненте, к которому вы пытаетесь получить доступeditingMemberName[index][index]
, который, скорее всего, не определен2. @YuriSh, я попытался просто пройти
editingMemberName
мимо, не добавив[index]
в конце, и получил ту же ошибку.
Ответ №1:
В React реквизиты передаются функциональным компонентам как единый объект. Ваша функция компонента предполагает, что реквизиты передаются как отдельные аргументы, а не в одном объекте.
Исправлено определение компонента (обратите внимание на скобки вокруг списка аргументов):
MemberItem = ({
member,
index,
editingMemberName,
editMemberName,
handleChangeName,
updateMemberName,
cancelEditMemberName,
destroyMember
}) => { ... }
Этот метод распаковки свойств называется деструктуризацией объектов.
Комментарии:
1. Я только что понял это буквально, когда вы опубликовали это решение.