I have this question about react rerendering and mount/unmount.
If we define a component inside of another parent functional component and the state of the parent component changes, it is clear that the parent component will re-render.
Question: But, does the child functional component defined inside of it re-render as well or it unmounts and then mounts again?
I am using the code below as a reference to this question. The issue with the code below is that when a user types , the focus is lost(or keyboard disappears in case of react-native) after every keystroke and the reason given by the author is that the child function gets redeclared when the Form function is re-rendered. but I am not sure what it means by re-declared, does it mean it gets re-rendered or get unmounted and get mounted again?
The solution to the problem(according to the author) is either to pass {Input()} or define the child component outside of the parent Form component.
This is the link for the original article https://levelup.gitconnected.com/code-review-avoid-declaring-react-component-inside-parent-component-1768a645f523
import { useState } from 'react';
const Form = () => {
const [values, setValues] = useState(['', '']);
const onChange = (value, index) => {
const newValues = [...values];
newValues[index] = value;
setValues(newValues);
};
const Input = (props) => {
return <input type='text' {...props} />;
};
return (
<>
{values.map((value, index) => (
<Input
key={index}
value={value}
onChange={(e) => onChange(e.target.value, index)}
/>
))}
<button onClick={() => setValues([...values, ''])}>Add</button>
</>
);
};
3
Answers
To understand this you must understand the reconciliation algorithm.
When during one render react sees some component somewhere in tree hierarchy, say:
and then on the next render it sees a different component:
in the same place in tree hierarchy, it unmounts
ComponentA
, and mountsComponentB
.Now, when you define a component inside another component, when the outer component re-renders, the inner component function (the one used to create the component) is recreated, and react will think that it is a different component type (because function reference is different now). Hence we get similar situation as with
ComponentA
andComponentB
.That’s why the component must be defined outside. When it is defined outside, the function used to create the component remains the same between re-renders (the reference also doesn’t change). In such case re-rendering parent will simply cause child to re-render, without unmounting.
In React, when a parent component undergoes re-rendering, its child components are also re-rendered automatically. In the provided code sample, the child component "Input" is defined within the parent component "Form". Thus, whenever "Form" is re-rendered, a new instance of "Input" is created.
This implies that when a state change triggers re-rendering of the "Form" component, the "Input" component also undergoes re-rendering. However, since a fresh instance of "Input" is generated each time "Form" re-renders, the previous instance of "Input" is unmounted and a new instance is mounted to replace it.
This could lead to issues such as the disappearance of the keyboard on every keystroke, as the newly mounted "Input" instance does not retain the same focus state as the previous instance. To avoid such issues, the "Input" component can be defined outside the "Form" component, which allows the same instance of "Input" to be reused on every re-rendering of "Form".
To summarize, by default, when a parent component is re-rendered in React, its child components are also re-rendered. However, if a child component is defined inside the parent component, it is re-declared on every re-rendering of the parent component, which leads to the old instance being unmounted and a new instance being mounted in its place
the child component (Input) is defined inside the parent component (Form). Every time the parent component re-renders, the function of the child component (Input) is re-declared. This means that the child component will be remounted, that means on every re-render of the parent component, the child component is a new function. This is why the focus is lost on every key press.