调用 REST API 并将其响应存储在 Context API 中
Posted
技术标签:
【中文标题】调用 REST API 并将其响应存储在 Context API 中【英文标题】:Call REST API and store its response in Context API 【发布时间】:2019-12-06 09:36:51 【问题描述】:我的 React 应用程序要求将 API 驱动的数据存储在 Context API 中。类函数不仅仅是我们使用的函数组件。
我尝试使用 await 和 fetch 调用,但没有成功
const App = props =>
const initState = props
return (
<AppContextProvider initState=initState>
<HoldingDetailsContainer initState=initState />
</AppContextProvider>
)
const AppContextProvider = (props) =>
const resources = useGetResourceApi();
const context =
resources
;
return (
<AppContext.Provider value=context>
props.children
</AppContext.Provider>
)
如果我在 useGetResourceApi
前面使用 await ,那么它会抛出错误“对象作为 React 子级无效(找到:[object Promise])。如果您要渲染一组子级,请改用数组。 "
是否可以在上下文 API 中存储 API 驱动的数据
【问题讨论】:
useGetResourceApi
是自定义钩子吗?
这是一个自定义函数,内部做axios调用
【参考方案1】:
我看不到您的 API 调用或 HoldingDetailsContainer 的详细信息,也看不到您的导入,但下面是使用 Context API + Hooks + 函数组件获取的完整(人为)示例通过 REST API 获取数据并将其提供给组件:
// App.jsx
import React from "react";
import APIContextProvider from "./apiContext";
import Users from "./Users";
export default function App()
return (
// wrap your app (or just components that need to consume the context)
<APIContextProvider>
<div className="App">
<h1>Hello CodeSandbox</h1>
// the Users component sits below the Provider so can consume its context
<Users />
</div>
</APIContextProvider>
);
// apiContext.jsx
import React, useContext, useState, useEffect, createContext from "react";
import axios from "axios";
const APIContext = createContext();
export function APIContextProvider( children )
// for more complex state you might set up useReducer for Redux-like state updates
const [users, setUsers] = useState([]);
// useEffect is a lifecycle method for function components, run once after mount
useEffect(() =>
// the callback to useEffect can't be async, but you can declare async within
async function fetchData()
// use the await keyword to grab the resolved promise value
// remember: await can only be used within async functions!
const data = await axios.get(
`https://jsonplaceholder.typicode.com/users`
);
// update local state with the retrieved data
setUsers(data);
// fetchData will only run once after mount as the deps array is empty
fetchData();
, []);
return (
<APIContext.Provider
// Add required values to the value prop within an object (my preference)
value=
users
>
children
</APIContext.Provider>
);
// Create a hook to use the APIContext, this is a Kent C. Dodds pattern
export function useAPI()
const context = useContext(APIContext);
if (context === undefined)
throw new Error("Context must be used within a Provider");
return context;
// 用户.jsx
import React from "react";
import useAPI from "./apiContext";
export default function Users()
// Now we can grab the data we want via useAPI, which abstracts useContext()
const users = useAPI();
return (
<ul>
// Now we can use the data from the API in our components
// ofc this simple example can be adapted to make further calls
users.map(u => (
<li key=u.id>u.username</li>
))
</ul>
);
可以在我整理的这个沙箱中找到上述代码的工作、实时版本:https://codesandbox.io/s/context-api-fetch-data-provider-example-0rymy
【讨论】:
哇!我喜欢代码中的 cmets。它几乎感觉就像一个完整的教程。非常感谢!【参考方案2】:请看这个要点:https://gist.github.com/nimahkh/9c008aaf2fd2d1cc83cd98c61e54979a
我认为你必须改变你的结构,在上下文中存储,就像存储在数据库或 redis 缓存中一样。 此外,在上下文中存储是一个异步过程,因此您必须获取 api,然后将其存储在上下文中。
我将通过我的要点示例向您展示代码
const App = () =>
const initialState =
theme: primary: 'green'
;
const reducer = (state, action) =>
switch (action.type)
case 'storeApi':
return
...state,
store_api: action.storeApi ;
default:
return state;
;
return (
<StateProvider initialState=initialState reducer=reducer>
<HoldingDetailsContainer />
</StateProvider>
);
然后我们将分派,我们的请求进入上下文
HoldingDetailsContainer 组件
const [data,setData]=useState();
function fethcData()
fetchApi().then(res=>
const data=res.data;
setData(data) //setData is useState function
)
//Now i need a side effect , to store data, after storing in state
useEffect(()=>
dispatch(
type: 'storeApi',
storeApi: data
)
)
【讨论】:
它正在工作,我能够在 conext 中存储 API 驱动的数据。再感谢一件事,我们可以从子组件更新提供者数据吗? 欢迎您,是的,您可以用我给您的示例发送它。以上是关于调用 REST API 并将其响应存储在 Context API 中的主要内容,如果未能解决你的问题,请参考以下文章
提高调用其他 API 的 Rest Webservice 性能的方法