MobX状态未更新问题:Page1列表计数器未随Page2修改同步
问题分析与解决方案
核心问题点
1. Store的updateRecord方法未修改实际数据
updateRecord方法中通过map生成了修改后的数组result,但没有将这个新数组赋值给this.data。Mobx依赖观察实例属性的变更来触发组件重渲染,所以这里的数据更新根本没有同步到Store中。
2. Page2错误地将API返回的记录转为字符串
调用JSON.stringify(json.data)把API返回的对象转成了字符串,导致传入updateRecord的record是字符串类型,而非对象。此时item.id === record.id的比较永远不成立(字符串没有id属性),无法匹配到目标记录完成更新。
3. Page1中冗余的Observer组件
TabTwoScreen已经被observer高阶组件包裹,内部嵌套的Observer属于不必要的重复监听,会增加额外的重渲染开销。
修正后的代码
Store代码修正(重点修复updateRecord)
class RecordStore { data: any[] = []; constructor() { makeAutoObservable(this); } // Get the list data from backend getRecordData = async() => { try { const response = await postRequest('record/get'); const json = response.data; const records = json.records; this.setData(records); } catch(error) { console.log(error); } }; // Set the data setData = (data: any) => { this.data = data; }; // Used to update a single record in the data, matching the IDs updateRecord = (record: any) => { // 将map生成的新数组赋值给this.data,触发Mobx的变更监听 this.data = this.data.map((item) => item.id === record.id ? record : item); } } // Instantiate the counter store. const counterStore = new RecordStore(); // Create a React Context with the counter store instance. export const CounterStoreContext = React.createContext(counterStore); export const useRecordStore = () => React.useContext(CounterStoreContext)
Page2代码修正(去掉字符串转换)
const Record = observer(() => { const { updateRecord } = useRecordStore(); // Submit the updated record to the API // API returns the record's json const onSubmit = async () => { try { const response = await postRequest('record/update', { recordId: record?.id, counter: counter }); const json = response.data; // 直接传递API返回的对象,无需转为字符串 updateRecord(json.data); } catch(error) { console.log(error); } } return ( // Simply shows a text field and a submit button ); }); export default Record;
Page1代码优化(移除冗余Observer)
const TabTwoScreen = observer(() => { const { data, getRecordData } = useRecordStore(); useEffect(() => { // Get the record data to populate the list getRecordData(); }, []); return ( <SafeAreaView> <View> <FlatList data={data} renderItem={({item}) => { return ( <Link href={{ pathname: "/record", params: { recordId: item.id } }} asChild> <Pressable> <View> <Text>{item.counter}</Text> </View> </Pressable> </Link> ) }} /> </View> </SafeAreaView> ); }); export default TabTwoScreen;
内容的提问来源于stack exchange,提问作者user2343632
相关产品推荐
相关产品推荐

