Brad Parks Brad Parks - 13 days ago 5
Javascript Question

Show/Hide ReactJS components without losing their internal state?

I've been hiding/showing react components by not rendering them, for example:

render: function() {
var partial;
if (this.state.currentPage === 'home') {
partial = <Home />;
} else if (this.state.currentPage === 'bio') {
partial = <Bio />;
} else {
partial = <h1>Not found</h1>
}
return (
<div>
<div>I am a menu that stays here</div>
<a href="#/home">Home</a> <a href="#/bio">Bio</a>
{partial}
</div>
);
}


but just say that the
<Bio/>
component has lots of internal state. Everytime I recreate the component, it loses it's internal state, and resets to it's original state.

I know of course that I could store the data for it somewhere, and pass it in via props or just globally access it, but this data doesn't really need to live outside of the component. I could also hide/show components using CSS (
display:none
), but I'd prefer to hide/show them as above.

What's the best practice here?

EDIT: Maybe a better way to state the problem is to use an example:

Ignore React, and assume you were just using a desktop app that had a configuration dialog with a Tab component called A, which has 2 tabs, named 1 and 2.

Say that tab A.1 has an email text field and you fill in your email address. Then you click on Tab A.2 for a second, then click back to Tab A.1. What's happened? Your email address wouldn't be there anymore, it would've been reset to nothing because the internal state wasn't stored anywhere.

Internalizing the state works as suggested in one of the answers below, but only for the component and it's immediate children. If you had components arbitrarily nested in other components, say Tabs in Tabs in Tabs, the only way for them to keep their internal state around is to either externalize it somewhere, or use the
display:none
approach which actually keeps all the child components around at all times.

It just seems to me that this type of data isn't data you want dirtying up your app state... or even want to even have to think about. It seems like data you should be able to control at a parent component level, and choose to either keep or discard, without using the
display:none
approach and without concerning yourself with details on how it's stored.

Answer

One option would be to move the conditional inside the component itself:

Bio = React.createClass({
    render: function() {
        if(this.props.show) {
            return <p>bio comp</p>
        } else {
            return null;
        }
    }
});

<Bio show={isBioPage} />

Whether this is "best practise" or not probably depends on the exact situation.

Comments