When writing a ReactJS component, I found the child component loses its state once a while. Turns out it happens if the child component is rendered with a different render function.
i.e.
Parent component has 2 sub-render functions and, due to different conditions, it either renders the child component in the body, or in the header.
...
renderInHeader = () => (<Header><ChildComponent /></Header>);
renderInBody = () => (<Body><ChildComponent /><Body>);
render = () => {
if (somethingHappens) {
return this.renderInHeader();
}
return this.renderInBody();
}
...
That means, when somethingHappens, it will use a different render function to render the ChildComponent.
Then, ChildComponent would lose its state. (Child component's state get reset).
I understand why it happens, I'm actually slightly surprised that the child's state doesn't get reset more often (i.e. reset every time parent re-render that node).
However, what's the ideal solution to deal with it?
Avoid using state in child component? (because it's not guaranteed safe?)
Give a
key=to the ChildComponent, so it can be treated as an independent node during re-render? (not sure ifkeyworks outside of mapper)Use
ref? (no idea if it works that way)Use new "Portal" from react 16? (haven't tried yet)
Note: I know I can use variable for Header and Body, so there's only one render function needed. However, a real world case could be more complicated, there may be multiple child components distributed in different areas.
i.e.
...
renderInBody = () => (
<Body>
<Header>
<ChildComponent1 />
<ChildComponent2 />
</Header>
<ChildComponent3 />
</Body>
);
renderInHeader = () => (
<Header>
<ChildComponent3 />
<ChildComponent1 />
<Body>
<ChildComponent2 />
</Body>
</Header>
);
render = () => {
if (somethingHappens) {
return this.renderInHeader();
}
return this.renderInBody();
}
...
Here, Child Component 1,2,3 doesn't really change, just their position and parent's structure gets changed.
And, I don't feel it's a good solution to put the Child Component positioning strategy in Header and Body components.
Is it possible to keep ChildComponent's state?