-1

I would like to show an informational message when a user creates a task in my app. I have worked in react for a while now, but I am unable to think of the logic to show messages that disappear after showing once.

Here's the current setup

App.js Main component which uses react router dom to route to different pages and looks like:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      taskCreated: false,
    };
  }

  showTaskCreatedAlert = () => {
    this.setState({ taskCreated: true });
  };

  render() {
    return (
        <Router>
          <div>
            <Switch>
              <Route 
                exact 
                path="/" 
                component={props => <TasksIndex {...this.state} />} 
              />
              <Route
                path="/users/new"
                component={props => (
                  <TasksNew
                    showTaskCreatedAlert={this.showUserCreatedAlert}
                    {...props}
                  />
                )}
              />
            </Switch>
          </div>
        </Router>
    );
  }
}

TasksNew.js Component that renders a form where a user can create tasks

When a task is successfully created, I update state on my parent component (App.js and set taskCreated to true. Then I push the history to the root resource "/".

TasksIndex.js Component that renders all tasks created by the user This component gets the main components state passed to it as props and depending on whether the taskCreated is set to true or false, it will display that informational message

Everything is fine except that message does not go away after the user navigates away to /users/new and comes back. Only on a full reload does it disappear. Now I know why this is happening: The state of the parent component is never updated and taskCreated remains true.

But then how to accomplish this? How can I get the message to disappear once the user navigates to a different page in the app. I want to accomplish this without redux.

Govind Rai
  • 14,406
  • 9
  • 72
  • 83
  • I think this link will help you get solved. [How to Pass variable to parent component](https://stackoverflow.com/questions/38394015/how-to-pass-data-from-child-component-to-its-parent-in-reactjs) – Mukundhan Sep 25 '17 at 05:48
  • First, use Route's "render" prop instead of "component". Second, I wonder if you could use TasksIndex's componentWillUnmount to set taskCreated back to false? – Tyler McGinnis Sep 25 '17 at 16:36

1 Answers1

0

What you need, is just to change the state taskCreated of your parent component to false, after any app route change. You can do it by subscribing to browser history:

import createBrowserHistory from 'history/createBrowserHistory'

const history = createBrowserHistory()

class App {
    constructor(props) {
         super(props);
         this.state = {
             taskCreated: false,
         };
    }

    showTaskCreatedAlert = () => {
         this.setState({ taskCreated: true });
    };

    componentDidMount() {
         // listen for changes of location
         this.unlisten = history.listen((location, action) => {
              this.setState({ taskCreated: false });
         });
    }
    componentWillUnmount() {
         // Remove your listener when your component is destroyed
         this.unlisten();
    }
    render() {
        <Router history={history}>
            // ...
        </Router>
    }
}
Borys Kupar
  • 1,631
  • 11
  • 24
  • My app component never unmounts. Only inner components mount/unmount. Also you are never supposed to call setState in componentWillUnmount. – Govind Rai Sep 25 '17 at 15:29
  • It's a good practice to remove any listener when component is unmounted, even though your app does not have this use case yet. "history.listen" call will return a unsubscribe function and set it to this.unlisten property. Later, in component unmount "this.unlisten()" is removing a history listener, and it will not call setState. – Borys Kupar Sep 25 '17 at 20:07