reactjsmobxmobx-react

React Mobx componentDidUpdate is not updating when observable changes


I'm new to Mobx and reactjs in general, I have knowledge in Redux and react native, and in Redux when I used to call an action and the props get updated, the componentDidUpdate life cycle method is triggered.

The scenario I'm having now is login. so the user fills the form, clicks submit, and the submit calls a Mobx action (asynchronous), and when the server responds, an observable is updated, and then it navigates to a main page (navigation happens in the component).

Here is my store code.

import { autorun, observable, action, runInAction, computed, useStrict } from 'mobx';

useStrict(true);

class LoginStore {
    @observable authenticated = false;
    @observable token = '';

    @computed get isAuthenticated() { return this.authenticated; }


    @action login = async (credentials) => {
        const res = await window.swaggerClient.Auth.login(credentials)l
        // checking response for erros
        runInAction(() => {
            this.token = res.obj.token;
            this.authenticated = true;
        });
    }
}

const store = new LoginStore();

export default store;

export { LoginStore };

and this handler is in my component.

handleSubmit = (e) => {
        e.preventDefault();

        this.props.form.validateFields((err, values) => {
            if (!err) {
                this.props.store.login(values);
            }
        });
    }

    componentDidUpdate() {
        if (this.props.store.isAuthenticated) {
            const cookies = new Cookies();
            cookies.set('_cookie_name', this.props.store.token);
            this.props.history.push('main');
        }
    }

It's not the ideal code, I'm just experimenting, but I'm not quite getting it.

Also, if I use the computed value (isAuthenticated) in the render life cycle method, the componentDidUpdate is triggered, but if I didn't use it in the render method, the componentDidUpdate is not triggered. For example, if I do this

render() {
  if (this.props.store.isAuthenticated) return null
  // .... rest of the code here
}

the above will trigger the componentDidUpdate.

Am I missing something? is there a better way to do it with Mobx? Thanks


Solution

  • Observer component will only react to observables referred in its render method. MobX documentation covers this.

    I would recommend you to use when to solve the problem.

    componentDidMount() {
      when(
        () => this.props.store.isAuthenticated,
        () => { 
          // put your navigation logic here
        }
      );
    }