Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reset component's internal state on route change

I am using react-router-v4 along with react 16.

I want to reset the component's internal state when the user go to a different route or comes back to the same route . Route change should destroy the internal state of a component but it doesn't . And I can't even find a way to notify the component when the route changes as it's a nested component not a direct render of a Route component. Please help.

Here's the code or live codepen example --

const initialProductNames = {
    names: [
        { "web applications": 1 },
        { "user interfaces": 0 },
        { "landing pages": 0 },
        { "corporate websites": 0 }
    ]
};

export class ProductNames extends React.Component {

state = {
    ...initialProductNames
};

animProductNames = () => {
    const newArray = [...this.state.names];
    let key = Object.keys(newArray[this.count])[0];
    newArray[this.count][key] = 0;

    setTimeout(() => {
        let count = this.count + 1;

        if (this.count + 1 === this.state.names.length) {
            this.count = 0;
            count = 0;
        } else {
            this.count++;
        }

        key = Object.keys(newArray[count])[0];
        newArray[count][key] = 1;
        this.setState({ names: newArray });
    }, 300);
};

count = 0;

componentDidMount() {
    this.interval = setInterval(() => {
        this.animProductNames();
    }, 2000);
}

componentWillUnmount() {
    clearInterval(this.interval);
}

componentWillReceiveProps(nextProps) {
    console.log(nextProps.match);
    if (this.props.match.path !== nextProps.match.path) {
        this.setState({ ...initialProductNames });
        this.count = 0;
    }
}

render() {
    return (
        <section className="home_products">
            <div className="product_names_container">
                I design & build <br />
                {this.createProductNames()}
            </div>
        </section>
    );
}

createProductNames = () => {
    return this.state.names.map(nameObj => {
        const [name] = Object.keys(nameObj);
        return (
            <span
                key={name}
                style={{ opacity: nameObj[name] }}
                className="product_names_anim">
                {name}
            </span>
        );
    });
};
}
like image 507
Ruhul Amin Avatar asked Jan 31 '18 05:01

Ruhul Amin


People also ask

Which method is used to change the component's state?

Always use the setState() method to change the state object, since it will ensure that the component knows it's been updated and calls the render() method.

Does React router reset state?

If you change it manually then you basically reload the app completely which resets the state.

How do I reset my React component state?

To reset a component to its initial state: When an event occurs, call the setState() function, passing it the initial state.

How do you set state after component did mount?

You may call setState() immediately in componentDidMount(). It will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won't see the intermediate state.


2 Answers

I got the solution . I didn't quit understood why state as property initializer doesn't reset/intialize on remount. I think it only initialize once, not on every route change] -

I wanted to know how to reset a component's state on route change. But it turns out that you don't have to . Each route renders a specific component . When route changes all other components are unmounted and all the state of those components are also destroyed. But see my code. I was using es7+ property initializer to declare state,count . That's why the state wasn't resetting/initializing again when the component remounted on route change.

To fix it, all i did is i put the state,initialProductNames,count; all of those into constructor. And now it's working perfectly .

Now fresh state on every mount and remount!!

like image 154
Ruhul Amin Avatar answered Sep 19 '22 07:09

Ruhul Amin


You can use a listener on the Route change as the example on this previous question And there you can add a function to update the main state.

  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      this.onRouteChanged();
    }
  }

  onRouteChanged() {
    console.log("ROUTE CHANGED");
  }
like image 35
Juan P. Ortiz Avatar answered Sep 19 '22 07:09

Juan P. Ortiz