I have two children Components, when I onChange
in first children, then the second children re render, I don't want to the second children re render. Online code example: https://codesandbox.io/s/billowing-glitter-r5gnh3?file=/src/App.js:1287-1297
const EditSceneModalStore = React.createContext(undefined);
const Parent = () => {
const [saveValue, setSaveValue] = React.useState({});
const initValue = {
name: "zhang",
age: 3
};
const onSave = () => {
console.log("===saveValue==", saveValue);
};
const onChangeValue = (key, value) => {
const newValue = {
...saveValue,
[key]: value
};
setSaveValue(newValue);
};
return (
<EditSceneModalStore.Provider
value={{
initValue,
onChangeValue
}}
>
<ChildInput1 />
<ChildInput2 />
<Button onClick={onSave} type="primary">
save
</Button>
</EditSceneModalStore.Provider>
);
};
const ChildInput1 = () => {
const { onChangeValue, initValue } = React.useContext(EditSceneModalStore);
const [value, setValue] = React.useState(initValue.name);
return (
<Input
value={value}
onChange={(v) => {
setValue(v.target.value);
onChangeValue("name", v.target.value);
}}
/>
);
};
const ChildInput2 = () => {
const { initValue, onChangeValue } = React.useContext(EditSceneModalStore);
const [value, setValue] = React.useState(initValue.InputNumber);
console.log("====ChildInput2===");
return (
<InputNumber
value={value}
onChange={(v) => {
setValue(v.target.value);
onChangeValue("age", v.target.value);
}}
/>
);
};
when I onChange in ChildInput1, then ChildInput2
re-render, I don't want to the ChildInput2
re-render. Example image
As Andrey explained, you should fix the following line:
//you have
const [value, setValue] = React.useState(initValue.InputNumber);
// should be
const [value, setValue] = React.useState(initValue.age);
Additionally, initValue
gets unnecessarily re-computed on every re-render, so it should be outside the scope of Parent
:
const initValue = {
name: "zhang",
age: 3
};
const Parent = () => {...}
Regarding re renderings, it is ok. When a Provider gets the value changed, all their childs wrapped in a consumer rerender. This is natural. This post explains why.
A component calling useContext will always re-render when the context value changes. If re-rendering the component is expensive, you can optimize it by using memoization.
In this case, it is not expensive enough to consider memoization.
I Hope it helps