Подкомпонент React не рендерится повторно при изменении свойств массива - PullRequest
0 голосов
/ 27 октября 2019

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

Первый подкомпонент обрабатывает число prop с model.myNumberProperty, а второй подкомпонент обрабатывает массив prop с model.myArrayProperty

Изменение model.myNumberProperty в подкомпоненте 1 запускает повторную визуализацию, но изменение model.myArrayProperty в подкомпоненте 2 не

function App() {
  const model = MyModel();

  return (
    <div className="App">
      Main app
      <ComponentOne dataObject={model} />
      <ComponentTwo dataObject={model} />
    </div>
  );
}

export default function MyModel() {
  let _propOne = 0;
  let _propTwo = ["one"];

  const propOne = () => {
    return _propOne;
  };
  const propTwo = () => {
    return _propTwo;
  };

  const modifyPropOne = () => {
    _propOne++;
    console.log("modifying prop one", _propOne);
  };

  const modifyPropTwo = () => {
    _propTwo.push("new element");
  };

  return Object.freeze({ propOne, propTwo, modifyPropOne, modifyPropTwo });
}


const ComponentOne = props => {
  const [propOne, setPropOne] = useState(props.dataObject.propOne());

  const onButtonOneClick = () => {
    props.dataObject.modifyPropOne();
    setPropOne(props.dataObject.propOne());
  };

  return (
    <div>
      <p>Hello ComponentOne:</p>

      <button onClick={onButtonOneClick}>ModifyPropOne</button>
      <p>{propOne}</p>
    </div>
  );
};

const ComponentTwo = props => {
  const [propTwo, setPropTwo] = useState(props.dataObject.propTwo());

  const onButtonTwoClick = () => {
    props.dataObject.modifyPropTwo();
    setPropTwo([...props.dataObject.propTwo()]);
    console.log('Prop two', props.dataObject.propTwo());
  };
  return (
    <div>
      <p>Hello ComponentTwo</p>

      <button onClick={onButtonTwoClick}>ModifyPropTwo</button>
      {propTwo.map((value, index) => (
        <p key={index}>{value}</p>
      ))}
    </div>
  );
};

Пожалуйста, посмотрите на этот CodeSandbox чтобы проверить дело.

Я использую React Hooks. Решением моей проблемы должно быть только React, поэтому никаких Redux или других сторонних библиотек.

Пожалуйста, обратите внимание, что моя модель - это замороженный объект для принудительной инкапсуляции, поэтому я не могу просто воссоздать весь объект. Модель в этом примере является уменьшенной и упрощенной. В моем реальном проекте это сложный объект карточной игры, который обрабатывает множество массивов.

1 Ответ

2 голосов
/ 27 октября 2019

При вызове setState React делает поверхностное сравнение с предыдущим состоянием и решает, должна ли фаза рендеринга продолжаться.

В вашем случае он имеет ту же ссылку, поэтому нетРендеринг сработал.

Чтобы исправить это, установите копию вашего массива в качестве нового состояния.

const onButtonTwoClick = () => {
  props.dataObject.modifyPropTwo();
  //                v Make a new copy.
  setPropTwo([...props.dataObject.propTwo()]);
};

См. Сила не мутирования данных .

Edit updateArrayProp

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...