Mobx修改Observable变量后React组件未重渲染问题求助
问题根源
问题出在——Provider和组件中的SorterSharedContextStore是完全独立的两个实例:
- AppProvider里创建了一个
sharedContextStore实例,调用setLoaded修改的是这个实例的loaded值 - 但组件
IndustionStationView里又重新new了一个全新的SorterSharedContextStore,这个实例的loaded从来没被改过,组件当然不会重新渲染
修复方法
要让组件能响应Provider里store的变化,必须让两者用同一个store实例,用Mobx的Provider+useStore就能实现共享:
第一步:修改AppProvider,把store传到Provider里
把创建好的sharedContextStore加到Provider的参数中,让子组件能拿到:
import React, { useEffect } from 'react'; import { Provider, useLocalObservable } from 'mobx-react'; import sorterRootStore from 'stores/sorter-root-store'; import { dataGET } from 'wes_shell_app/api-utils'; import { SorterSharedContextStore } from 'stores/sorter-shared-context-store'; import { IAPIInductionStationModel } from 'models/server-models'; export const AppProvider = ({ children }: React.PropsWithChildren) => { const state = useLocalObservable(() => ({ sharedContextStore: new SorterSharedContextStore(), })); useEffect(() => { const fetchData = async () => { try { const path = 'getInductionStations'; const response: IAPIInductionStationModel = await dataGET(`?????????${path}`); state.sharedContextStore.setInductionStations(response); state.sharedContextStore.setLoaded(); console.log(state.sharedContextStore.loaded); } catch (error) { console.error('Error fetching data:', error); } }; fetchData(); }, []); // 将sharedContextStore加入Provider的传递列表 return ( <Provider rootStore={sorterRootStore} sharedContextStore={state.sharedContextStore}> {children} </Provider> ); };
第二步:组件里用共享的store,别自己new
组件里通过useStore获取Provider传递过来的实例,不要重新创建:
import { observer, useStore } from "mobx-react"; import { SimpleCard } from "wes_shell_app/simpleCard"; import BaseView from "wes_shell_app/base-view"; import { useEffect } from "react"; import { SorterInductionStationViewStore } from "../stores/sorter-induction-station-view-store"; import { SorterInductionStationDataProvider } from "../stores/data/sorter-induction-station-data-provider"; import { SorterSharedContextStore } from "stores/sorter-shared-context-store"; import { IClientWaveInfoModel } from "models/client-models"; import { FormLabel } from "@mui/material"; import LocalizedText from "wes_shell_app/localized-text"; type InductionStationViewType = { id: number; }; const IndustionStationView = observer(({ id }: InductionStationViewType) => { const provider = new SorterInductionStationDataProvider(); const store = new SorterInductionStationViewStore(); const waveInfo: IClientWaveInfoModel = store.waveInfo; // 从Provider获取共享的store实例 const sharedContextStore = useStore((store) => store.sharedContextStore); useEffect(() => { sharedContextStore.setActualInductionStationID(id); store.openConnection(); return () => { store.closeConnection(); }; }, [id, sharedContextStore]); // 添加必要的依赖项 if (sharedContextStore.loaded === "true") return <div>Loading...{sharedContextStore.loaded}</div>; return ( <BaseView cardBackgroundColor={false}> <div className="flex gap-5"> <SimpleCard> <FormLabel className="text-xs" sx={{ fontSize: "0.75em" }}> <LocalizedText intlId="Info" /> </FormLabel> <p className="text-2xl font-bold mt-3">FLOOR - On Floor Lab Sorter{waveInfo && waveInfo.sorter}</p> <p className="mt-2">ID: 3{waveInfo && waveInfo.sorterid}</p> </SimpleCard> </div> </BaseView> ); }); export default IndustionStationView;
额外提醒
- 组件已经用
observer包裹,这部分没问题,Mobx才能追踪observable变量的变化 - useEffect的依赖项要加全,避免闭包导致拿不到最新的store值
- SorterStore里
makeObservable的写法是正确的,确保了loaded是可观察变量、setLoaded是action
内容的提问来源于stack exchange,提问作者xttx
相关产品推荐
相关产品推荐

