Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

125
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda