skip to Main Content

I pass a component state as a prop to another component. It is really large. Do I have to reset the state while parent component unmounted? I just want to avoid memory leaks.

componentDidMount(){
  fetch({ /* ... */ })
    .then(res => res.json())
    .then((responseData) => {
      this.setState({
        result: responseData.meta.data
      })
    })
}
  
componentWillUnmount(){
  this.setState({
    result: undefined // IS THAT RIGHT APPROACH?
  })
}

render() {
  return (
    <DataComponent data={this.state.result}>

    </DataComponent>
  );
}

3

Answers


  1. If your component uses custom element.addEventListener()s, then you will want to use removeEventListener() in your componentWillUnmount() function. Otherwise, all the clean up for state, onClick, and other React-specific functionality is done automatically.

    A use case where I’ve needed to clean up event listeners is when I was using a custom vanilla-JS library that didn’t have a React equivalent and I had to manually set up and later remove listeners. If I didn’t and I recreated the JS component, then events would be handled twice (or more depending on how many times the component was recreated) causing weird things to happen.

    Login or Signup to reply.
  2. Do I have to reset the state while parent component unmounted?

    You don’t need to cull the local component state, React/Javascript handles garbage collecting it when it is no longer referenced.

    There’s also no point an enqueueing a state update in componentWillUnmount since the component is unmounting and there will be no further render cycle.

    Note also from the componentWillUnmount docs:

    componentWillUnmount()

    componentWillUnmount()
    

    componentWillUnmount() is invoked immediately before a component is
    unmounted and destroyed. Perform any necessary cleanup in this method,
    such as invalidating timers, canceling network requests, or cleaning
    up any subscriptions that were created in componentDidMount().

    You should not call setState() in componentWillUnmount() because
    the component will never be re-rendered. Once a component instance is
    unmounted, it will never be mounted again.

    Use this lifecycle method to clean up non-state-related code, like event listeners, timers, subscriptions, cancel in-flight network requests, etc.

    controller = null;
    
    componentDidMount() {
      this.controller = new AbortController();
      const { signal } = this.controller;
    
      fetch({ /* ... */ }, { signal })
        .then(res => res.json())
        .then((responseData) => {
          this.setState({
            result: responseData.meta.data
          });
        });
    }
      
    componentWillUnmount() {
      this.controller?.abort();
    }
    
    Login or Signup to reply.
  3. To prevent memory leaks, you don’t have to perform this state change in componentWillUnmount method. Unmounting the component would remove the state, and so would the reference to the responseData.meta.data, which you stated is large.

    There is also another downside to this solution. This type of optimization lowers your code readability and may complicate the maintenance process in future. So try not to use this in your code as it is considered against the clean code principle.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search