Search code examples
reactjsmobxmobx-react-lite

observer from 'mobx-react-lite' not working


I just started to practice react mobx and now I have a problem. the observer not working. it seems it not observing the store. this should load some activity list from api and during loading show the icon (loading). and after loaded datas it should show the activities in boxes. it loads correctly from api and I can see in network inspect tabs. the problem is exactly in observer . here is my activityStore:

import { action, observable } from "mobx";
import { createContext } from "react";
import agent from "../api/agent";
import { IActivity } from "../models/activity";

class ActivityStore {
  @observable activities: IActivity[] = [];
  @observable loadingInitial = false;

  @action loadActivities = () => {
    this.loadingInitial = true;
    agent.Activities.list()
      .then((activities) => {
        activities.forEach((activity) => {
          activity.date = activity.date.split(".")[0];
          this.activities.push(activity);
        });
      })
      .finally(() => {
        this.loadingInitial = false;
      });
  };
}

export default createContext(new ActivityStore());

and I used App.tsx like this:

import { observer } from "mobx-react-lite";
import ActivityStore from "../stores/activityStore";
import some component from semantic ui react and other codes;

const App = () => {
  const activityStore = useContext(ActivityStore);

  useEffect(() => {
    activityStore.loadActivities();
  }, [activityStore]);

  if (activityStore.loadingInitial)
    return <LoadingComponent content="loading..." inverted={true} />;
  return (
    <Fragment>
      <NavBar createActivity={handleOpenCreateForm} />
      <Container style={{ marginTop: "7em" }}>
        <ActivityDashboard
          activities={activityStore.activities}
        />
      </Container>
    </Fragment>
  );
};

export default observer(App);

Solution

  • I finally find the problem. in new version of mobx-react-lite you need to call 'makeObservable' in 'constructor' like below:

    class ActivityStore {
      @observable activities: IActivity[] = [];
      @observable loadingInitial = false;
    
    constructor() {
        makeObservable(this);
      }
    
      @action loadActivities = () => {
        this.loadingInitial = true;
        agent.Activities.list()
          .then((activities) => {
            activities.forEach((activity) => {
              activity.date = activity.date.split(".")[0];
              this.activities.push(activity);
            });
          })
          .finally(() => {
            this.loadingInitial = false;
          });
      };
    }