Интересно, в чем причина того, что ReactJS не заставляет повторно применять CSS к событию дочернего компонента, если вызывается componentDidUpdate(). Я сделал небольшую демонстрацию и добавление нового блока не меняет цвет для существующих блоков, хотя номера меняются.

Добавление коробок Демо

И как я могу заставить его обновить.

Спасибо

1
atadnmz 21 Фев 2020 в 15:54

2 ответа

Лучший ответ

Основной принцип ReactJS заключается в том, что обновляются только измененные объекты в DOM. Эта модульность дает вам все преимущества скорости, простоты и абстрактности, даже если ваш сайт содержит тысячи компонентов.

В вашем примере вы добавляете новый блок в DOM, и ни один из других блоков не изменяется, ReactJS проверяет это автоматически при каждом render().

Таким образом, ответ на ваш вопрос относительно прост: если вы хотите, чтобы другие ящики были перерисованы, вам нужно как-то изменить их. В противном случае ReactJS не поймет, что другие блоки нужно перерисовать. Самый простой способ добиться этого - использовать свойство key, см. документация:

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

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

Теперь, если вы измените ключи при добавлении нового элемента в DOM, объекты будут перерисованы, потому что при изменении key ReactJS понимает, что этот объект необходимо перерисовать. Вы также можете изменить другие атрибуты для повторного отображения объекта, но изменение key является наиболее прямым способом.

Кроме того, вы также можете позвонить forceUpdate(), см. Документацию, но вам все равно нужно изменить разметку:

По умолчанию, когда состояние вашего компонента или реквизит меняются, ваш компонент будет повторно визуализироваться. Если ваш метод render () зависит от некоторых других данных, вы можете указать React, что компонент нуждается в повторном рендеринге, вызвав forceUpdate ().

Вызов forceUpdate () вызовет render () для компонент, пропуская shouldComponentUpdate (). Это вызовет обычные методы жизненного цикла для дочерних компонентов, включая Метод shouldComponentUpdate () каждого дочернего элемента. Реагировать все равно будет только обновить DOM, если разметка изменится .

Обычно вы должны стараться избегать любого использования forceUpdate () и читать только из this.props и this.state в render ().

3
Jean-Paul 21 Фев 2020 в 13:15

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

class App extends React.Component {
  state = {
    data: [1, 2, 3]
  };

  handler = () => {
    this.setState({ data: this.state.data.concat(this.state.data.length + 1) });
  };

  render() {
    return (
      <div>
        <button onClick={this.handler}>Add</button>
        {this.state.data.map(box => {
          return (
            <Box
              key={makeid(5)}
              click={this.handler}
              val={Math.floor(Math.random() * 10) + 1}
            />
          );
        })}
      </div>
    );
  }
}

function makeid(length) {
  var result = "";
  var characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  var charactersLength = characters.length;
  for (var i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}

Я использую функцию makeId для создания случайного нового ключа при каждом рендеринге. Это, вероятно, НЕ лучший способ сделать это для большинства случаев использования, это просто иллюстративно

https://codesandbox.io/s/angry-wu-8h6km

1
TKoL 21 Фев 2020 в 13:09