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

Обратитесь к этой песочнице, где у меня есть написано два способа присвоения ключа компоненту, отображаемому внутри итерации.

Определение компонента

const Component = (props) => {
  const { id } = props;
  return <div key={id}>This is a component</div>;
};

Определение стека компонентов:

const componentStack = [{ Component }, { Component }];

Метод А:

...
{componentStack.map((el) => (
   <el.Component key={a uniquekey} />
))}
...

Метод Б:

...
{componentStack.map((el) => (
   <el.Component id={a uniquekey} />
))}
...

Отредактировано: я отредактировал свой вопрос. Я думаю, что метод Б должен быть неправильным. Но чем он отличается от метода А?


Отредактировано: я добавил фрагменты кода для лучшего понимания.

1
HaoSiong Ng 6 Июл 2021 в 08:24

4 ответа

Лучший ответ

Ключ похож на идентификатор, но для целей рендеринга.

Ключи помогают React определить, какие элементы были изменены, добавлены или удаленный. Ключи должны быть даны элементам внутри массива, чтобы придать элементам стабильную идентичность:

Ключевые атрибуты используются в response, чтобы определить, изменился ли элемент. Вы можете думать об этом как об идентификаторе фиксации. Если объект изменился и, следовательно, изменился его идентификатор, react будет повторно отображать его.

Как я уже сказал выше ... ключ предназначен для рендеринга.

Вот пример

const { useState, useEffect } = React;

const availableColors = [
  {
    name: "IndianRed",
    value: "#CD5C5C"
  },
  {
    name: "PeachPuff",
    value: "#FFDAB9"
  },
  {
    name: "SlateBlue",
    value: "#6A5ACD"
  },
  {
    name: "DarkSeaGreen",
    value: "#8FBC8B"
  }
];

const Colors = (props) => {
  const [colors, setColors] = useState(availableColors);

  useEffect(() => {
    const timerId = setInterval(() => {
      const newColors = [...colors];
      shuffle(newColors);
      setColors(newColors);
    }, 2000);
    return () => {
      clearInterval(timerId);
    };
  }, []);

  return (
    <div>
      <ul className="list-group">
        {colors.map((color) => {
          return (
            <li className="list-group-item" key={color.value} style={{ background: color.value }}>
              {color.name}
            </li>
          );
        })}
      </ul>
    </div>
  );
};

function shuffle(array) {
  var currentIndex = array.length,
    randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {
    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;

    // And swap it with the current element.
    [array[currentIndex], array[randomIndex]] = [
      array[randomIndex],
      array[currentIndex]
    ];
  }

  return array;
}

ReactDOM.render(<Colors />, document.getElementById("root"));
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Теперь, когда вы посмотрите на DevTools (F12), вы увидите разница в обновлениях DOM.

Обновления DOM БЕЗ ключей

Заменен почти весь элемент DOM.

DOM updates without keys

Обновления DOM с ключами

Поскольку элемент DOM не изменился, он просто перемещается.

enter image description here

2
René Link 6 Июл 2021 в 06:53

Ключ должен быть уникальным. Вместо getDate () используйте getTime (), как показано ниже в

{componentStack.map((el) => (
        <el.Component key={new Date().getTime()} />
))}
1
Avani Bataviya 6 Июл 2021 в 05:42

Насколько мне известно, React автоматически обновляет компоненты на основе их key.

Если у вас есть несколько компонентов одного и того же типа, вы бы хотели иметь уникальный key для каждого из них, поэтому react может обновлять их по отдельности, иначе он обновит их все.

Поэтому рекомендуется уникальная опора key (см. Консоль). Опора id не предоставляет key.

Отредактируйте ваш комментарий: в документации React (в разделе «Извлечение компонентов с помощью ключей») говорится, что key должен быть указан в компоненте, который возвращает функция map, потому что React получает доступ к значению key каждого элемента в массиве (которое возвращается map).

Если вы передадите значение key дочернему элементу компонента в массиве, React не сможет получить к нему доступ.

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

1
Einliterflasche 6 Июл 2021 в 05:58

Я очень признателен за все ответы на мой вопрос. Однако я думаю, что я задал вопрос неправильно, когда данные объяснения не дали ответа на вопрос в моей голове. Мне действительно интересно, зачем назначать ключ компоненту

<el.Component key={"a unique key"} />

Отличается от назначения внутри компонента с помощью prop

const {id} = props;
return <Component key={id} />

Что ж, я наконец понимаю, что назначение ключа внутри компонента фактически присваивается самому компоненту. Представление предложения return является дочерним компонентом и просто назначает ключ этому дочернему элементу. Думаю, именно поэтому код не работает.

0
HaoSiong Ng 6 Июл 2021 в 07:42