Search code examples
reactjsuse-effectmobx

Mobx - UseEffect hook not executing when item in dependency list is changed


I'm new to React and Mobx.

I want the useEffect hook in the code below to execute whenever the dates are changed. The date variables are inside a store. Whenever I change the date, I expect the useEffect in my component to execute, but it only executes when the component is first initialized.

I added the store as an item in the useEfftcts dependency list, but no luck. Any help would be greatly appreciated.

Here is my component

const TeamDashboard: React.FC<IProps> = ({ teams, teamName, teamSchedule }) => {
  const teamsStore = useContext(TeamsStore);
  const datesStore = useContext(DatesStore);

  let teamIds: number[] = [];

  useEffect(() => {
    teams.map((team) => {
      teamIds.push(team.id);
    });

    teamsStore.loadScheudle(
      teamSchedule,
      teamIds,
      datesStore.startDate,
      datesStore.endDate
    );
  }, [datesStore]);

  return (
    <Container></Container>
  );
};
export default observer(TeamDashboard);

Here is my Date Store

class DatesStore {
    @observable startDate: Date = new Date();
    @observable endDate: Date = new Date('2021-04-05');

    @action setStartDate = (event: any, data: any, ) => {
        data.value > this.endDate
        ? this.startDate = new Date()
        : this.startDate = data.value === null ? seasonStartDate : data.value;
    }

    @action setEndDate = (event: any, data: any) => {
        console.log(data.value);
        this.endDate = data.value === null ? seasonEndDate : data.value;
    }
}

export default createContext(new DatesStore())

Solution

  • Making use of makeAutoObservable from Mobx Version 6 and removing the action and observables decorators resolved the useEffect to execute when the Date changed in my store. Below is how my code is set up now.

    Date Store

    export default class DatesStore {
        startDate: Date = new Date();
        endDate: Date = new Date();
    
        constructor() {
            this.endDate.setDate(this.startDate.getDate() + parseInt('30'));
            makeAutoObservable(this);
        }
    
        setStartDate = (event: any, data: any, ) => {
            data.value > this.endDate
            ? this.startDate = new Date()
            : this.startDate = data.value === null ? seasonStartDate : data.value;
        }
    
        setEndDate = (event: any, data: any) => {
            this.endDate = data.value === null ? seasonEndDate : data.value;
        }
    }
    

    Root Store that stores all the stores and a custom hook to use the stores in my components

    interface Store {
        teamsStore: TeamsStore,
        datesStore: DatesStore
    }
    
    export const store: Store = {
        teamsStore: new TeamsStore(),
        datesStore: new DatesStore()
    }
    
    export const StoreContext = createContext(store);
    
    export function useStore() {
        return useContext(StoreContext)
    }
    

    The Component in question

    const TeamDashboard: React.FC<IProps> = ({ teams, teamName, teamSchedule }) => {
      const { teamsStore, datesStore } = useStore();
    
      teams.slice().sort((a, b) => b.points - a.points);
      let teamIds: number[] = [];
    
      useEffect(() => {
        teams.map((team) => {
          teamIds.push(team.id);
        });
    
        teamsStore.loadScheudle(
          teamSchedule,
          teamIds,
          datesStore.startDate,
          datesStore.endDate
        );
      }, [datesStore.startDate, datesStore.endDate]);
    
      return (
        <Container></Container>
      );
    };
    export default observer(TeamDashboard);