Search code examples
reactjsmobxmobx-state-tree

Mobx. parent component is not re-rendered?


I'm learning mobx. I can not understand why the parent component is not re-rendered. When the button is clicked, the value of the field in the observed object changes. The parent component is an observer. Why isn't it updated? I made two versions: just mobx and mobx - state - tree. None work.

Mobx

import React, { useContext , createContext} from 'react'
import { observer} from 'mobx-react-lite';
import { observable } from 'mobx'


const TestOb = observable({
    Name: 'Test'    
});

const StoreContext = createContext(TestOb);

const ChildComp = () => {
    const store = useContext(StoreContext)
    const clickHandle = () => {     
        store.Name = "Test 2";       
    }
    return (
        <div>
            <button onClick={clickHandle}>Click</button>
        </div>
    )
}

 const Test = () => {

    console.log("Test comp"); // does not fire on change
    
    return (
        <StoreContext.Provider value={TestOb}>
            <div>
                <ChildComp />
            </div>
        </StoreContext.Provider>
    )
}

export default observer(Test);

mobx-state-tree

import React, { useContext, createContext } from 'react'
import { observer, types } from 'mobx-react-lite';
import { observable } from 'mobx'
import { types } from 'mobx-state-tree'


const TestStore = observable(types.model({
    Name: types.maybe(types.string)
}).actions(self => {
    return {
        setName: () => { self.Name = "Test" }
    }
}))
const store = TestStore.create({});

const StoreContext = createContext(store);


const ChildComp = () => {
    const store = useContext(StoreContext)
    
    const clickHandle = () => {
        store.setName();
    }
    return (
        <div>
            <button onClick={clickHandle}>Click</button>
        </div>
    )
}

const Test = () => {
    console.log("Test"); // does not fire on change
    return (
        <StoreContext.Provider value={TestOb}>
            <div>
                <ChildComp />
            </div>
        </StoreContext.Provider>
    )
}

export default observer(Test);

Solution

  • An observer component will re-render when observable data it depends on changes.

    Your Test component is currently not dereferencing any observable data. You could try to use TestOb.Name to see it working.

    Example

    const Test = () => {
      console.log("Test comp");
    
      return (
        <StoreContext.Provider value={TestOb}>
          <div>
            {TestOb.Name}
            <ChildComp />
          </div>
        </StoreContext.Provider>
      );
    };