Situation: I'm attempting to write a "tabbed" application, where each tab's view is based on a complex and stateful component. I'm able to organize and render this, however the state in each tab's component does not persist - e.g. if I have two tabs derived from the same component (each one containing a stateful <input /> child), and I edit the <input /> in one, it will be wiped clean when I navigate to the other tab and back.
I've been through a number of separate implementation attempts. At first, I thought I'd store the tab components in a Redux store - but Redux (understandably) doesn't like this, as they're not serializable. I then tried the solution recommended in https://github.com/reduxjs/redux/issues/1793 - storing unique keys in the Redux store, and using those to reference a collection of components which are maintained in a parent component's state (parent to the tabs). I.e. the tabs kept in my store have a .uid property, which I use to retrieve the associated page component in my Content parent component via contentPages[uid] (where contentPages is just an object of {[uid]: Component} pairs). At this point, I don't understand React well enough to know why the component's states aren't persisting. I've tried adding unique keys in various places thinking that might have been the issue, but it doesn't seem to change anything. (If it matters, I'm using functional components for everything).
Question: How do I persist complex React components and their associated state?
Example Code:
function Content() {
const [contentPages, setContentPages] = useState({});
const uid = useSelector(activeTabUidSelector));
...
return (
<div className="parent">
<Tabs /> // Renders the actual tabs
<div className="content-display">{contentPages[uid]}</div> // Renders the content of the current active tab
</div>
)
}
Where contentPages[uid] could be any number of components, but in the case I'm working through happens to look something like the following:
function NewTab() {
const [text, setText] = useState("");
const handleChange = (event) => setText(event.target.value);
return (
<div className="new-tab">
<input value={text} onChange={handleChange} />
</div>
)
}