Reactjs 在功能组件中使用RESTAPI调用更新React上下文

Reactjs 在功能组件中使用RESTAPI调用更新React上下文,reactjs,react-context,Reactjs,React Context,我正在尝试使用对后端REST API的API调用产生的数据更新React应用程序的上下文。问题是我无法同步该函数 我尝试过这篇博文中建议的解决方案,但对我的情况不起作用 下面是textContext.js的代码 import React, {useEffect, useState} from "react"; import axios from "axios"; var text = "Test"; fetch(process.env.REACT_APP_TEXT_API) .the

我正在尝试使用对后端REST API的API调用产生的数据更新React应用程序的上下文。问题是我无法同步该函数

我尝试过这篇博文中建议的解决方案,但对我的情况不起作用

下面是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;
    })
}


我试图使用useffect函数获取Profile.js中的数据

 const [text, setText] = useState(null);
  useEffect(()=> {
    setText (callTextApi())
  },[])

这是我第一次使用React.context,它非常混乱。我做错了什么或遗漏了什么?

我看到的第一件事是,您没有在函数中返回承诺,这将导致将状态设置为未定义

我在下面添加了返回语句:

export async function callTextApi () {
  return await fetch(process.env.REACT_APP_TEXT_API)
    .then(res => res.json())
    .then(json => {
      return json;
    })
}
另外,您的最后一个then链可以稍微清理一下,我确信您可以在返回承诺时删除异步函数中的WAIT语句。将自动等待:

export async function callTextApi () {
  return fetch(process.env.REACT_APP_TEXT_API)
    .then(res => res.json())
    .then(json => json)
}
第二步是看看你的
useffect
hook。在api调用的承诺得到解决后,您需要
setText
。因此,还必须使
useffect
的回调函数异步

  useEffect(async ()=> {
    const newText = await callTextApi();
    setText (newText);
  },[])
第三步是了解如何正确使用上下文api和
useContext
hook。
useContext
hook将上下文作为参数,但您将ContextProvider作为参数传递

const text = useContext(TextContext);
上下文和上下文提供程序是React世界中的两个不同实体。将上下文视为希望在应用程序中共享的状态和功能(如全局状态),并将提供程序视为管理一个上下文并将此上下文状态提供给其子组件的react组件

return(
<TextContext.Provider value={/* some value */}>
    {children}
</TextContext.Provider>);
返回(
{儿童}
);

这就是提供者组件的返回语句的样子,我认为您的应用程序中目前缺少这段代码。

这里有很多问题<代码>获取和更改应该通过修改
属性在
提供程序内部进行
useContext
接收整个
Context
对象,而不仅仅是
提供程序
。检查以下各项

//Context.js
export const context = React.createContext()
现在在您的
提供商中

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>
   )
}
请记住,
Component
必须位于
MyProvider

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>
   )
}
更新

  • 什么是
    {children}
组件
声明中的所有内容都映射到
props.children

const App = () =>{
    return(
        <Button>
            Title
        </Button>
    )
}

const Button = props =>{
    const { children } = props

    return(
        <button className='fancy-button'>
            { children /* Title */}
        </button>
    )
}
这里的
children
RestOfMyApp

  • 如何访问Profile.js中提供程序的值
使用
createContext
。让我们假设
提供者的
属性是
{foo:'bar'}

const Component = () =>{
    const content = useContext(context)

    console.log(content) //{ foo : 'bar' }
}
  • 如何像在提供程序中那样双重声明常量
这是一个输入错误,我改为
MyProvider

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>
   )
}
从基于
类的组件中访问它

class Component extends React.Component{
    render(){
        const { Consumer } = context
        return(
             <Consumer>
                 {
                     context => console.log(contxt) // { foo: 'bar' }
                 }
             </Consumer>
        )
    }
}
类组件扩展React.Component{
render(){
const{Consumer}=context
返回(
{
context=>console.log(contxt)/{foo:'bar'}
}
)
}
}

我有一些问题可能会让我理解这里发生了什么。首先,什么是{儿童}?其次,如何访问Profile.js中提供程序的值?第三,如何像在提供程序中那样双重声明常量?有关和的详细信息,请参见此处。@Dopocas,您的实现可以很好地处理类,但功能组件如何?如何访问上下文的值?与
功能组件
配合良好。你想知道如何在基于类的组件中访问上下文表单吗?@Dupocas在他的回答中很好地解释了所有不同的原则,一般来说,现在你应该能够将这些原则应用到你的应用程序中
fetchData
只是一个普通的例子。在代码中,它应该是
callTextApi()
。他只是想举例说明如何调用获取数据的函数。提供程序将上下文作为其状态保存,您可以通过调用setText()更新该状态。提供者组件应该包装希望访问上下文的应用程序组件,包装的组件称为children,@Dupocas在他的回答中也提到了这一点。