How to keep React component state between mount/unmount?

react prevent component from unmounting
react unmount child component
componentwillreceiveprops
react-router prevent unmount
unmount functional component react
react clear state on unmount
react maintain state on refresh
when does a react component unmount

I have a simple component <StatefulView> that maintains an internal state. I have another component <App> that toggles whether or not <StatefulView> is rendered.

However, I want to keep <StatefulView>'s internal state between mounting/unmouting.

I figured I could instantiate the component in <App> and then control whether its rendered/mounted.

var StatefulView = React.createClass({
  getInitialState: function() {
    return {
      count: 0
    }
  },
  inc: function() {
    this.setState({count: this.state.count+1})
  },
  render: function() {
    return (
        <div>
          <button onClick={this.inc}>inc</button>
          <div>count:{this.state.count}</div>
        </div>
    )
  }
});

var App = React.createClass({
  getInitialState: function() {
    return {
      show: true,
      component: <StatefulView/>
    }
  },
  toggle: function() {
    this.setState({show: !this.state.show})
  },
  render: function() {
    var content = this.state.show ? this.state.component : false
    return (
      <div>
        <button onClick={this.toggle}>toggle</button>
        {content}
      </div>
    )
  }
});

This apparently doesnt work and a new <StatefulView> is created on each toggle.

Here's a JSFiddle.

Is there a way to hang on to the same component after it is unmounted so it can be re-mounted?

The most important decision is where to keep the state when the component unmounts.

Some options:

  1. React state in parent: If a parent component remains mounted, maybe it should be the owner of the state or could provide an initial state to an uncontrolled component below. You can pass the value back up before the component unmounts. With React context you can hoist the state to the very top of your app (see e.g. unstated).
  2. Outside of React: E.g. use-local-storage-state. Note that you might need to manually reset the state inbetween tests. Other options are query params in the URL, MobX, Redux, etc.

I've you're looking for an easy solution where the data is persisted outside of React, this Hook might come in handy:

const memoryState = {};

function useMemoryState(key, initialState) {
  const [state, setState] = useState(() => {
    const hasMemoryValue = Object.prototype.hasOwnProperty.call(memoryState, key);
    if (hasMemoryValue) {
      return memoryState[key]
    } else {
      return typeof initialState === 'function' ? initialState() : initialState;
    }
  });

  function onChange(nextState) {
    memoryState[key] = nextState;
    setState(nextState);
  }

  return [state, onChange];
}

Usage:

const [todos, setTodos] = useMemoryState('todos', ['Buy milk']);

How to maintain state between mount/unmount? · Issue #4345 , Is it possible to instantiate a component, then mount, unmount, and remount it allowing the component to maintain its internal state/context? I'm trying to make something similar to NavigatorIOS from React Native. Technically the constructor is the first function called upon instantiating any class in JS, not just React Components. That being said, the constructor has an important role in the life of a component, as it acts as a perfect place to set the initial state of a component. Within the constructor, one can initialize state like so:

OK. So after talking with a bunch of people, it turns out that there is no way to save an instance of a component. Thus, we HAVE to save it elsewhere.

1) The most obvious place to save the state is within the parent component.

This isn't an option for me because I'm trying to push and pop views from a UINavigationController-like object.

2) You can save the state elsewhere, like a Flux store, or in some global object.

This also isn't the best option for me because it would be a nightmare keeping track of which data belongs to which view in which Navigation controller, etc.

3) Pass a mutable object to save and restore the state from.

This was a suggestion I found while commenting in various issue tickets on React's Github repo. This seems to be the way to go for me because I can create a mutable object and pass it as props, then re-render the same object with the same mutable prop.

I've actually modified it a little to be more generalized and I'm using functions instead of mutable objects. I think this is more sane -- immutable data is always preferable to me. Here's what I'm doing:

function createInstance() {
  var func = null;
  return {
    save: function(f) {
      func = f;
    },
    restore: function(context) {
      func && func(context);
    }
  }
}

Now in getInitialState I'm creating a new instance for the component:

component: <StatefulView instance={createInstance()}/>

Then in the StatefulView I just need to save and restore in componentWillMount and componentWillUnmount.

componentWillMount: function() {
  this.props.instance.restore(this)
},
componentWillUnmount: function() {
  var state = this.state
  this.props.instance.save(function(ctx){
    ctx.setState(state)
  })
}

And that's it. It works really well for me. Now I can treat the components as if they're instances :)

How to save component state between unmount/mount in react-redux?, How to save component state between unmount/mount in react-redux? Basically I want to restore the last state of a component when re-mounting it. Storing the  No. The state is part of the instance. If state should be maintained then it probably doesn't belong in the component itself and should live in some data store, or the parent (and passed in as props). You could do something a little bit clever and have a hidden prop instead of unmounting. Then just render null when hidden or something.

React Component Mounting And Unmounting, Learn about React Component Mounting And Unmounting. the syntax above or below, keep in mind that they accomplish the same task. state = { key: "value" }. How to save component state between unmount/mount in react-redux? Basically I want to restore the last state of a component when re-mounting it. Storing the state in the parent component is not really an option for me, because the parent component also gets unmounted with the child.

Hmm, you could use localStorage, or AsyncStorage if React Native.

React Web

componentWillUnmount() {
  localStorage.setItem('someSavedState', JSON.stringify(this.state))
}

Then later that day or 2 seconds later:

componentWillMount() {
  const rehydrate = JSON.parse(localStorage.getItem('someSavedState'))
  this.setState(rehydrate)
}

React Native

import { AsyncStorage } from 'react-native'

async componentWillMount() {
  try {
    const result = await AsyncStorage.setItem('someSavedState', JSON.stringify(this.state))
    return result
  } catch (e) {
    return null
  }
}

Then later that day or 2 seconds later:

async componentWillMount() {
  try {
    const data = await AsyncStorage.getItem('someSavedState')
    const rehydrate = JSON.parse(data)
    return this.setState(rehydrate)
  } catch (e) {
    return null
  }
}

You could also use Redux and pass the data into the child component when it renders. You might benefit from researching serializing state and the second parameter of the Redux createStore function which is for rehydrating an initial state.

Just note that JSON.stringify() is an expensive operation, so you should not do it on keypress, etc. If you have concern, investigate debouncing.

Keep a React component mounted, from the DOM in the specified container, and clean up any of its event handlers and state. Today in this tutorial, we will learn how to do mounting and unmounting in ReactJS. A React component’s life-cycle have different phases for creation and deletion. In coding terms, these are known as mounting and unmounting. In other words, you can also say that “Setup” and “Cleanup”. Phases which we are using in Setup and Cleanup:

I'm late to the party but if you're using Redux. You'll get that behaviour almost out of the box with redux-persist. Just add its autoRehydrate to the store then it will be listening to REHYDRATE actions that will automatically restore previous state of the component (from web storage).

Can we unmount a component manually?, performs an update that does not render this instance. This is useful if you want to unmount your root component especially if you have a react app residing in a non-react app. I had to use this because I wanted to render react inside a modal handled by another app, and their modal have close buttons that will hide the modal but my reactdom will still remain mounted.

Component Lifecycle, ) by using Prompt . You need to manually pass the getUserConfirmation prop which is a function. You can modify this function as you like in any Router(Browser, Memory or Hash) to create your custom confirmation dialog(eg. React-router: never unmount a component on a route once mounted, even if route change. ( AuthenticatedRoute is a dumb component that checks the session, and either call <Route component= {component} /> or <Redirect to= {to} />, but at last, component method is invoked) Where basically each component is mounted/unmounted on route change.

How can I prevent the unmount in React Components?, Warning: Can only update a mounted or mounting component. remove the interval on componentWillUnmount() , you will update state on an  How to Mount and Unmount React Components. A simple example of a mountable component that illustrates the component lifecycle of React components and how to use them. A Pen by Joshua Michael Waggoner on CodePen. License.

React Lifecycle, This page introduces the concept of state and lifecycle in a React component. declare special methods on the component class to run some code when a component mounts and unmounts: Note how we save the timer ID right on this ( this. The constructor for a React component is called before it is mounted. When implementing the constructor for a React.Component subclass, you should call super (props) before any other statement. Otherwise, this.props will be undefined in the constructor, which can lead to bugs.

Comments
  • you could store the state on a Store using Flux
  • yeah, I was trying not to have save/load methods. Also, this could get tricky for me. Think about this in the context of a UINavigationController -- I may have multiple of the same exact component, but with different states, at different levels in the navigation stack...
  • Just a warning to others this is not going to work with testing or Components that get used in more than one spot.
  • This looks exactly like something I would need. Could you elaborate a bit more? Give an example of storing the state of component and restoring it in real life?
  • This is a great fix, Thanks
  • I had the same situation, I didn't go for persist library just because I wanted a common pattern which should happen even if the users are different. Just use redux
  • localStorage is interesting concept for web, will give it a go. Thanks
  • localStorage is secure. You can store up to about 15 MB of data in it, depending on browser, etc. It works very well for short term persistent data.
  • How about performance? Does it take time to read/write local storage compared to mutating global state of react app? muting state potentially rerender a whole lot of components which is why I am also looking for a solution to save a single components state between unmount/mount. But only in a performant way.
  • I would say performance is the secondary main concern after just getting the data to persist through dismounts. Storing data in upstream components is basically "lifting state" in React. This is more performant than saving data to disk because you are changing the reference to the data in-memory and basically avoiding garbage collection, so read/write speed will be turbo; however, storing the data in localStorage allows the data to persist as the root component itself is unmounted and remounted.
  • yeah, thats not what I'm getting at though. This is a contrived example so what you mention would work for this example, but not for the more complicated issue I'm trying to solve...
  • Your question was about maintaining the component specifically. As far as I know the best you can do is maintain the component's state and re-instantiate the component.
  • I see. Thats as far as I know as well. The less contrived version is this: I'm trying to build UITabBarController and UINavigationController equivalents for the web. With the UINavigationController specifically, we can be pushing arbitrary views to the stack and popping them off. Its not really feasible to keep track of all that arbitrary state so it would be great if I could keep the state within the component itself between mounting...