Почему «ключ» не распространяется на реагирующие элементы в карте элементов {children}? - PullRequest
0 голосов
/ 14 июля 2020

Я реализую компонент, который упрощает пользователям добавление нескольких элементов на страницу. Поскольку у меня есть несколько типов элементов, которые могут быть добавлены пользователем, я подумал, что было бы наиболее полезно иметь один компонент с параметром «children».

Однако у реализации проблемы с «ключом» параметр при сопоставлении дочерних элементов.

function ExpandableSet({
   startingSet,
   itemTitle,
   children
})
{

   const largestId = useMemo(() => {
      return startingSet.reduce((largestId, item) =>
         if (item.id > largestId){
            return item.id
         }
         return largestId
      }, 0)
   }, [])

   const [itemCount, setItemCount] = useState(largestId + 1);
   const [items, setItems] = useState(startingSet);

   return(
      <div className="expandable-set">
         { items.map( item =>
            <div className="expanded-item" id={item['key']} key={item['key']}> { children } </div>
         )}
      </div>
      <button onClick={() =>
         {
            items.push({"key" : itemCount});
            setItemCount(itemCount + 1);
         }
      }>
         Add {itemTitle}
      </button>
   )
}

Когда используется ExpandableSet, он используется следующим образом:

...
<div className="container-for-expandable-set">
   <ExpandableSet
      startingSet={[]}
      itemTitle="Some item I want a lot of" />
      <SomeItem opts=opts />
   </ExpandableSet>
</div>
...

Поскольку я не знаю, сколько SomeItem элементов там будет, невозможно передать ключи на родительском уровне без управления состоянием и там. Это нарушит назначение компонента ExpandableSet (может быть, это правильный ответ?)

Когда это выводится, я вижу стандартную ошибку each child in a list should have a unique 'key' prop.

HTML Вывод

...
<div class="expandable-set">
 <div class="expanded-item" id="0">
  <div class="child-template-passed">
   ...
  </div>
 </div>
 <div class="expanded-item" id="1">
  <div class="child-template-passed">
   ...
  </div>
 </div>
</div>
...

Почему я все еще вижу ошибку key?

1 Ответ

2 голосов
/ 14 июля 2020

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

Итак, если я добавлю элемент в набор через на странице, у нее будет нулевой идентификатор. Но что, если элемент в начальном наборе уже имеет нулевой идентификатор? Теперь у вас есть повторяющийся идентификатор в наборе.

Вам нужно найти самый большой идентификатор в начальном наборе и использовать этот идентификатор плюс один в качестве начального значения для itemCount.

const largestID = useMemo(() => {
  return startingSet.reduce((largestID, item) => {
    if (item.key > largestID) {
      return item.key
    }
    return largestID
  }, 0)
}, [startingSet])

const [items, setItems] = useState(startingSet);
const [itemCount, setItemCount] = useState(largestID + 1);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...