Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

113
Views
Why mobX action doesn't trigger rerendering of React component

I have a weird behavior of MobX.

Here is my store in the file store.tsx. You can find it also as a sandbox.

import { action, makeObservable, observable} from "mobx";

export default class ViewStore {
  currentProjectId: string | undefined = undefined;

  constructor() {
    makeObservable(this, {
      currentProjectId: observable,
      setCurrentProjectId: action,
    });
  }

  setCurrentProjectId = (projectId: string | undefined) => {
    this.currentProjectId = projectId;
  };
}

And here is my component

import React from "react";
import { observer } from "mobx-react-lite";
import { useParams } from "react-router-dom";

import ViewStore from "./store";

interface Props {
  localStore: ViewStore;
}

interface UrlParams {
  projectId: string;
}

function AppManageProject({ localStore }: Props) {
  const urlParams = useParams<UrlParams>();

  if (localStore.currentProjectId !== urlParams.projectId) {
    localStore.setCurrentProjectId(urlParams.projectId);
    return <></>;
  }

  return (
        <div>{localStore.currentProjectId}</div>
  );
}

export default observer(AppManageProject);

The page is part of a larger app and it's reached from the route /<project id>. When you first browse to e.g. /prj1, the if block is executed, so the observable currentProjectId is set to "prj1" via the MobX action setCurrentProjectId. I expect the change of the observable to trigger a rerendering, where now urlParams.projectId === localStore.currentProjectId. But the component is actually not rerendered.

In the sandbox, from the printout in the console, you can se that you do enter in the if block, but the rerendering is not triggered.

Notice that if instead of calling the action setCurrentProjectId directly, I use a callback, e.g. setTimeout(() => localStore.setCurrentProjectId(urlParams.projectId), 0) then everything works.

Thinking that the callback works because it uses an arrow function, I also tried to replace

localStore.setCurrentProjectId(urlParams.projectId)

with a call to an arrow function:

( () => localStore.setCurrentProjectId(urlParams.projectId) ) ()

But this also doesn't work.

Does anyone have any explanation/solution of what is going on? Thank you

about 4 years ago · Santiago Trujillo
1 answers
Answer question

0

For some reason MobX does not rerender components if you update some observable right inside of the render function. I don't know exactly why, but side effects inside render function is a bad pattern anyway, so it's kinda makes sense that it does not work.

What you can do to make you code more idiomatic is to use useEffect hook for side effects, like that:

function AppManageProject({ localStore }: Props) {
  const urlParams = useParams<UrlParams>();

  useEffect(() => {
    localStore.setCurrentProjectId(urlParams.projectId);
  }, [urlParams.projectId]);

  if (localStore.currentProjectId !== urlParams.projectId) {
    return <></>;
  }

  return <div>{localStore.currentProjectId}</div>;
}
about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!