Когда вам нужно позаботиться об этом
Если вы создадите обратный вызов при рендеринге и передадите его дочернему компоненту, реквизиты этого дочернего элемента будут изменены.Тем не менее, обычный компонент будет перерисовываться (в виртуальный дом), когда родительский рендеринг, даже реквизиты остаются прежнимиИсключением является classComponent, который реализует shouldComponentUpdate и сравнивает реквизиты (такие как PureComponent).
Это оптимизация, и вы должны заботиться о ней только в том случае, если перерисовка дочернего компонента требует значительных вычислений (если вы визуализируете его на один и тот же экран несколько раз или если он потребует глубокого или значительного повторного воспроизведения).
В этом случае вы должны убедиться, что: 1. Ваш ребенок является компонентом класса, который расширяет PureComponent 2. Избегайте передачи вновь созданной функции в качестве реквизита.Вместо того, чтобы передать диспетчер, установщик возвратил из React.useState или запомненного настроенного установщика.
Использование запомненного настроенного установщика
Хотя я бы не рекомендовал создавать уникальный запомненный установщик для определенного компонента (тамэто несколько вещей, на которые нужно обратить внимание), вы можете использовать общий хук, который позаботится о реализации для вас.
Вот пример хука useObjState, который предоставляет простой API и который не вызовет дополнительных повторных визуализаций.
const useObjState = initialObj => {
const [obj, setObj] = React.useState(initialObj);
const memoizedSetObj = React.useMemo(() => {
const helper = {};
Object.keys(initialObj).forEach(key => {
helper[key] = newVal =>
setObj(prevObj => ({ ...prevObj, [key]: newVal }));
});
return helper;
}, []);
return [obj, memoizedSetObj];
};
function App() {
const [user, memoizedSetUser] = useObjState({
id: 1,
name: "ed",
age: null,
});
return (
<NameComp
setter={memoizedSetUser.name}
name={user.name}
/>
);
}
const NameComp = ({name, setter}) => (
<div>
<h1>{name}</h1>
<input
value={name}
onChange={e => setter(e.target.value)}
/>
</div>
)
Демо