Trí Phan
Trí Phan

Reputation: 1193

React Hooks: useState() makes all children component re-rendered although the change doesn't affect some of them

Okay. Here is my situation. I have a big component called TheForm. In TheForm, there are the following children: TextEditor, TagInput, TipCard - this gives the advice how to write a good form and Preview:

const TheForm = () => {
  const [parag1, writeParag1] = useState("");
  const [parag2, writeParag2] = useState("");
  const [tags, updateTags] = useState([]);

  return (
    <div>
     <TipCard>Some suggestion here...</TipCard>
     Paragraph One: <TextEditor onInput={writeParag1}/>
     Paragraph One: <TextEditor onInput={writeParag2}/>
     Add tags: <TagInput onInput={updateTags}/>
     Preview Mode: <Preview />
     <button>Submit</button>
     <button>Reset</button>
    </div>
  );
}

The TextEditor contains a <textarea>, some buttons to format text, everytimes the value of the <textarea> changes, the proper state in TheForm is updated. Same for TagInput.

The Preview will take the state values and render them in preview mode (just like Stack Overflow ask a question).

The problem here is when one of the states is updated, it causes all the children re-rendered, even they are not using that state and even I used the React.memo for the component.

I know that when the state changes, it make the component re-rendered, so the children of the component are re-rendered too.

So how can I avoid that? I know that I can move the states down to the children, but if I do it, the Preview can not access those value. Redux can solve this problem, but is it too much to use Redux here, I mean those states are not shared with other component so using Redux is too much?

Upvotes: 0

Views: 446

Answers (1)

Yozi
Yozi

Reputation: 12727

It is just how React works - it run render function every time state is changed and it cause all children to re-render too, no matter are they depended on changed state or not.

If you would like to avoid re-render of a component, you can make it pure, e.g. wrap it with React.memo. So you have to wrap each child in order to prevent it re-render.

Pure components shallow compare props to determinate if it safe to skip re-render requested from a parent. It means, you have to not only wrap children to memo but ensure the props passed to them is persistent each time of render. Usually it means you should memoize callback like onInput={el => updateTitle(el.target.value)} with useMemo or useCallback and avoid, flatten or memoize objects like previewMode={{ title, description, codeBlock, tagList }} otherwise they will be re-created each time and it will invalidate shallow-compare optimisation

Upvotes: 1

Related Questions