0

I'm trying to get mobx to work with my react hooks and I am starting off with a very simple example but it still does not work. I must have missed something but I have been trying for hours to find what that might be.

Here is my store:

import { observable, decorate } from 'mobx';
import { createContext } from 'react';
import { IUser } from '../models/IUser';

export class UserStore {
    public user: IUser;

    public getUser() {
        myApi
            .get(myUrl)
            .then(response => {
                this.user = response;
            });
    }
}

decorate(UserStore, {
    user: observable,
});

export default createContext(new UserStore());

And here is the component printing the username of the user:

import React, { useContext } from 'react';
import { observer } from 'mobx-react-lite';
import UserStore from '../../stores/UserStore';

const MyComponent = observer(() => {
    const userStore = useContext(UserStore);

    return (
        <div>
            {userStore.user && userStore.user.userName}
        </div>
    );
});

export default MyComponent;

And to fire the api call, App does the following:

const App: React.FC = () => {
    const userStore = useContext(UserStore);

    useEffect(() => {
        userStore.getUser();
    }, []);

    return(...);
};

export default App;

I can see that 1: App performs the call 2: The user is set to the response of the call 3: If I console log the userStore.user.userName after it has been set, it looks just fine.

The quirk is that the label in MyComponent never gets updated. Why?

Heddelin
  • 206
  • 1
  • 9
  • And by the way, this splendid example works and I have done all I can to mimic it but something won't work... https://codesandbox.io/s/classic-mobx-stores-with-hooks-me334 – Heddelin Aug 23 '19 at 11:17

1 Answers1

0

I believe the bug is in decorate. Changing the behavior from using the decorate syntax, to wrapping the FC with observable works just fine, like this:

const UserStore = observable({
    user: {}
});

Another thing that also works is to have your stores as classes and using the old decorator syntax like this:

export class UserStore {
    @observable public user: IUser;
}

This requires you to add the following to .babelrc:

["@babel/plugin-proposal-decorators", { "legacy": true }]
Heddelin
  • 206
  • 1
  • 9