#javascript #reactjs
#javascript #reactjs
Вопрос:
Я везде читал, что изменяющееся состояние в React может вызвать проблему, например, компонент не будет повторно отображаться при обновлении состояния, но следующий код работает отлично. Компонент повторно отображает каждый раз, когда происходит обновление состояния.
import React, { useState, useEffect } from "react";
const Mutator = () => {
const [checks, setChecks] = useState({ 66: false });
const rows = [{ id: 23 }, { id: 33 }, { id: 44 }, { id: 55 }];
useEffect(() => {
console.log("check updates", checks);
}, [checks]);
const mutateMyCheck = () => {
rows.forEach((row, i) => {
checks[row.id] = checks[row.id] ? checks[row.id] i : 1;
});
setChecks({ ...checks });
};
return (
<div>
<button onClick={mutateMyCheck}>Check</button>
<div>{JSON.stringify(checks)}</div>
</div>
);
};
Какой смысл тогда не изменять состояние? Или когда это действительно имеет эффект?
Ответ №1:
Вы изменяете состояние напрямую, но вы также возвращаете новый объект через распространение объекта:
setChecks({ ...checks });
Поскольку это создает новый объект, компонент повторно отображает.
Комментарии:
1. Это. Кроме того, нет абсолютно никаких причин изменять состояние в прилагаемом примере. То же самое может быть достигнуто с помощью
Array.prototype.map()
илиArray.prototype.reduce()
2. Правда, хотя это скорее предпочтение стиля, reduce на самом деле не делает его чище, поэтому не упоминал —
rows.reduce((obj, row, i) => ({ ...obj, [row.id]: checks[row.id] ? checks[row.id] i : 1, }), {})
Также, если строки находятся в 1000-х годах, я бы не стал распространять каждую итерацию подобным образом, но каждый раз возвращал бы один и тот же объект (мутированный), поскольку он значительно медленнее, поэтому в случае 1000s было бы похоже на цикл изменения, чтобы быть эффективным.3. В этом точном случае это решение о стиле. Но если учесть возможные последствия мутаций состояния, оно перестает быть единым; ваше состояние отличается от того, что отобразил DOM, или представьте, что у вас подключено несколько хуков. Или просто подумайте о путанице, которую это вносит.
Ответ №2:
mutateMyCheck(); mutateMyCheck();
Это не увеличит количество проверок в два раза.
В этом случае вам следует использовать редуктор.