我正在尝试使用后端对REST API的API调用产生的数据来更新React App的上下文。问题是我无法同步功能。
我已经尝试过此博客文章https://medium.com/@__davidflanagan/react-hooks-context-state-and-effects-aa899d8c8014中建议的解决方案,但不适用于我的情况。
这是textContext.js的代码
import React, {useEffect, useState} from "react";
import axios from "axios";
var text = "Test";
fetch(process.env.REACT_APP_TEXT_API)
.then(res => res.json())
.then(json => {
text = json;
})
const TextContext = React.createContext(text);
export const TextProvider = TextContext.Provider;
export const TextConsumer = TextContext.Consumer;
export default TextContext
这是我尝试从上下文访问数据的功能组件
import TextProvider, {callTextApi} from "../../../../services/textService/textContext";
function Profile()
{
const text = useContext(TextProvider);
console.log(text);
const useStyles = makeStyles(theme => ({
margin: {
margin: theme.spacing(1)
}
}));
我可以在浏览器控制台的网络部分看到获取请求获取数据,但是上下文没有更新。
我尝试在textContext.js中执行此操作。
export async function callTextApi () {
await fetch(process.env.REACT_APP_TEXT_API)
.then(res => res.json())
.then(json => {
return json;
})
}
我当时正试图使用useEffect函数在Profile.js中获取数据
const [text, setText] = useState(null);
useEffect(()=> {
setText (callTextApi())
},[])
这是我第一次使用React.context,这非常令人困惑。我在做错什么或想念什么?
答案 0 :(得分:3)
您在这里遇到很多问题。 fetching
,并且应该通过修改Provider
value
在property
内部进行更改。 useContext
不仅接收Context
,还接收整个Provider
对象。检查以下内容
//Context.js
export const context = React.createContext()
现在进入您的Provider
import { context } from './Context'
const MyProvider = ({children}) =>{
const [data, setData] = useState(null)
useEffect(() =>{
fetchData().then(res => setData(res.data))
},[])
const { Provider } = context
return(
<Provider value={data}>
{children}
</Provider>
)
}
现在您有一个Provider
,它可以获取一些data
并将其传递到value
道具内。要从functional component
内部使用它,请像这样使用useContext
import { context } from './Context'
const Component = () =>{
const data = useContext(context)
return <SomeJSX />
}
请记住,Component
必须在MyProvider
下
更新
{ children }
? Component
声明中的所有内容都映射到props.children
。
const App = () =>{
return(
<Button>
Title
</Button>
)
}
const Button = props =>{
const { children } = props
return(
<button className='fancy-button'>
{ children /* Title */}
</button>
)
}
像({ children })
一样声明它只是const { children } = props
的快捷方式。我正在使用children
,以便您可以像这样使用Provider
<MyProvider>
<RestOfMyApp />
</MyProvider>
这里children
是RestOfMyApp
使用createContext
。假设您的value
的{{1}}属性为Provider
{foo: 'bar'}
那是一个错字,我改成了const Component = () =>{
const content = useContext(context)
console.log(content) //{ foo : 'bar' }
}
要从基于MyProvider
的组件内部访问它
class
答案 1 :(得分:0)
我看到的第一件事是您没有在函数中返回promise,这将导致将状态设置为undefined。
我在下面添加了return语句:
export async function callTextApi () {
return await fetch(process.env.REACT_APP_TEXT_API)
.then(res => res.json())
.then(json => {
return json;
})
}
也可以对您的最后一个then链进行清理,我很确定您可以在返回promise时在异步函数中删除await语句。它将自动等待:
export async function callTextApi () {
return fetch(process.env.REACT_APP_TEXT_API)
.then(res => res.json())
.then(json => json)
}
第二步是查看您的useEffect
钩子。您想在解决api调用的承诺后setText
。因此,您还必须使useEffect
的回调函数异步。
useEffect(async ()=> {
const newText = await callTextApi();
setText (newText);
},[])
第三步,将研究如何正确使用上下文api和useContext
钩子。 useContext
挂钩将上下文作为参数,但是您将ContextProvider传递为参数。
const text = useContext(TextContext);
上下文和上下文提供者是React世界中的两个不同实体。将上下文视为要在应用程序中共享的状态和功能(例如全局状态),并将提供者视为管理一个上下文并将此上下文状态提供给其子组件的React组件。
return(
<TextContext.Provider value={/* some value */}>
{children}
</TextContext.Provider>);
这是提供程序组件的return语句的外观,我认为您的应用程序中目前缺少此代码。