javascript - 设置状态时,React context api 返回未定义

标签 javascript reactjs react-redux react-hooks react-context

我最近开始学习 React,并使用 context api 来存储我的全局状态。

MyProvider.js 文件中,我定义了我的提供程序,它仅存储 2 个 json obj 数组

import {MyContext} from "./MyContext";
import React, {useState} from "react";

export const MyProvider = (props) => {
    const intialState = {
        featuredListings: [],
        setFeaturedListings: (val) => setState({...state, featuredListings: val}),
        featuredVendors: [],
        setFeaturedVendors: (val) => setState({...state, featuredVendors: val})
    }

    const [state, setState] = useState(intialState)

    return (
        <MyContext.Provider
            value={state}
        >
            {props.children}
        </MyContext.Provider>
    );
}

我通过这样做将所有组件包装在提供程序的 App.js 中,而不使用 ReachRouter 来处理路由,

<MyProvider>
    <div className="content">
        <Header/>
        <Router>
            <Home path="/"/>
        </Router>
    </div>
    <Footer />
</MyProvider>

在我的 Home.js 文件中,我在 useEffect Hook 中进行了一次网络调用,该调用成功返回了我期望的 json,并使用该 json 响应更新了上下文的状态,以便它可以全局可见。

我的代码是

export const Home = () => {
    let state = useContext(MyContext)

    async function apiCalls() {
        const featuredVendors = await getFeaturedVendors()
        console.log("featuredVendors - ", featuredVendors) // the correct response is returned
        state.setFeaturedVendors(featuredVendors)

        const featuredListings = await getFeaturedListing()
        console.log("featuredListings - ", featuredListings) // the correct response is returned
        state.setFeaturedListings(featuredListings)
    }

    useEffect(() => {
        apiCalls()
    }, []);

    return (
        <div>
            {console.log(state.featuredVendors)}  // empty array
            {console.log(state.featuredListings)} // contains correct values
        </div>
    )
}

]

为了消除任何歧义,我的上下文是在一个名为 MyContext.js 的单独文件中创建的 我像这样创建上下文

export const MyContext = React.createContext()

为什么当我设置时,state.featuredVendors没有更新?

我注意到的另一件奇怪的事情是,如果我重新排列调用的顺序,即调用 getFeaturedListing 首先是getFeaturedVendors,然后我的状态仅更新featuredVendors 和featuredListings 将是一个空数组。

最佳答案

当您调用useState时,initialValue仅设置一次。首次安装 MyProvider 时,会使用 setFeaturedListingssetFeaturedVendors 方法初始化状态,但只要 state 的值发生变化,这些状态就不会更新。因此,当您传播值时,state 的值将始终是其初始值。

setState 也可以使用始终接收当前值作为参数的函数来调用,因此您可以重写这些方法来传播该值,如下所示:

    const intialState = {
        featuredListings: [],
        setFeaturedListings: (val) => setState(state => ({...state, featuredListings: val})),
        featuredVendors: [],
        setFeaturedVendors: (val) => setState(state => ({...state, featuredVendors: val}))
    }

或者,您也可以将这些功能完全移出您所在的州。

export const MyProvider = (props) => {
  const intialState = {
      featuredListings: [],
      featuredVendors: [],
  }
  const [state, setState] = useState(intialState)
  return (
      <MyContext.Provider
          value={{
            ...state,
            setFeaturedListings: (val) => setState({...state, featuredListings: val}),
            setFeaturedVendors: (val) => setState({...state, featuredVendors: val})
          }}
      >
          {props.children}
      </MyContext.Provider>
  );
}

关于javascript - 设置状态时,React context api 返回未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60066770/

相关文章:

javascript - 同一类对象上的动画,一次一个

reactjs - 您是否应该在 Redux 中间件内多次调度或调用 next ?

javascript - 在react-json-tree中显示HTML标签

javascript - CSS 过渡 : Animating between inline styles for "height" style attribute

javascript - 使用 jQuery 定位动态 HTML

javascript - css jquery 复选框切换显示

reactjs - React原生组件中的高阶组件(HOC)和继承有什么区别

reactjs - 组件未更新深度嵌套的 redux 对象

reactjs - 镭安装与 react 17.0.2一起使用时出错

javascript - React Redux Redux Form - 从 <Field> 内移动函数会产生错误