Как отобразить массив объектов в другом файле в React?

#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. Я только что понял это буквально, когда вы опубликовали это решение.