我有多个小表,当应用程序更新相应的表时,我希望能够写入/读取/更新我的组件(我们暂时可以认为它是一个单用户应用程序)。我受到这个问题的启发,在我的应用程序中编写了一个自定义提供程序和关联的用于数据获取(并最终发布)的钩子:React useReducer async data fetch我想出了这个:import React from "react";import { useContext, useState, useEffect } from "react";import axios from "axios";const MetadataContext = React.createContext();function MetadataContextProvider(props) { let [metadata, setMetadata] = useState({}); async function loadMetadata(url) { let response = await axios.get(url); // here when I console.log the value of metadata I get {} all the time setMetadata({ ...metadata, [url]: response.data }); } async function postNewItem(url, payload) { await axios.post(url, payload); let response = await axios.get(url); setMetadata({ ...metadata, [url]: response.data }); } return ( <MetadataContext.Provider value={{ metadata, loadMetadata, postNewItem }}> {props.children} </MetadataContext.Provider> );}function useMetadataTable(url) { // this hook's goal is to allow loading data in the context provider // when required by some component const context = useContext(MetadataContext); useEffect(() => { context.loadMetadata(url); }, []); return [ context.metadata[url], () => context.loadMetadata(url), (payload) => context.postNewItem(url, payload), ];}function TestComponent({ url }) { const [metadata, loadMetadata, postNewItem] = useMetadataTable(url); // not using loadMetadata and postNewItem here return ( <> <p> {JSON.stringify(metadata)} </p> </> );}(代码应该在 CRA 上下文中运行,两个 API 都可以替换为几乎任何 API)当我运行它时,会在两个端点(/api/capteur 和 /api/observation)上触发请求,但我期望 MetadataContextProvider 中的元数据对象有 2 个键:“/api/capteur”和“/ api/observation”,只显示最后一次请求的内容。当我在 loadMetadata 函数中 console.log 元数据时,元数据始终具有初始状态挂钩值,即 {}。我对 React 还很陌生,我努力尝试过,但我真的不明白这里发生了什么。有人可以帮忙吗?
1 回答
一只萌萌小番薯
TA贡献1795条经验 获得超7个赞
您的问题是如何使用 更新metadata
对象setMetadata
。metadata
在您的上下文中通过更新对象的操作loadMetadata
分别由两个“实例”完成:TestComponent
#1 和TestComponent
#2。它们都可以访问metadata
上下文中的对象,但它们不会立即同步,因为useState
的 setter 函数是异步工作的。
解决您的问题的简单方法称为功能更新。 useState
的 setter 还提供了一个回调函数,它将使用(我在这里过于简单化)“最新”状态。
在您的上下文提供者中:
async function loadMetadata(url) {
let response = await axios.get(url);
setMetadata((existingData) => ({ ...existingData, [url]: response.data }));
// instead of
// setMetadata({ ...metadata, [url]: response.data });
}
添加回答
举报
0/150
提交
取消