无法从 useContext 访问 dispatch

问题描述

我有一个简单的商店

import React,{ createContext,useReducer } from "react";
import Reducer from "./UserReducer";

const initialState = {
    user: {},error: null
};

const Store = ({ children }) => {
    const [state,dispatch] = useReducer(Reducer,initialState);
    return (
        <Context.Provider value={[state,dispatch]}>
            {children}
        </Context.Provider>
    );
};

export const Context = createContext(initialState);
export default Store;

我已经用它包裹了我的应用程序

<Store>
    <ThemeProvider theme={Theme}>
        <CssBaseline />
        <Navbar />
        <Wrapper>
            <Profile />
        </Wrapper>
    </ThemeProvider>{" "}
</Store>

还有其他设置,我的身份验证页面位于单独的包装器中,所以我也用商店包装了它。

这是该包装器的代码(额外删除)。

import Store from "../../../context/Store";
export default function Wrapper({ children }) {
    const classes = useStyles();
    return (
        <Store>
           //different dumb containers opening
                {children}
          //different dumb containers closing
        </Store>
    );
}

现在当我尝试访问子组件中的上下文时

import React,{ useContext } from "react";
import { Context } from "../../../context/Store";
import { SET_USER } from "../../../context/UserTypes";

function SignUp(props) {
    const [state,setState] = React.useState({ ...initialState });

    const [userData,dispatch] = useContext(Context);
    console.log(userData,dispatch,"check");
// rest of component

出现以下错误

TypeError: undefined is not a function

我试图在不解构它的情况下记录 useContext 的结果,但它只有全局状态,但没有调度功能

Reactjs 版本 = 17.0.1

更新:dispatch 可以在 withAuthenticator HOC 外部访问,但不能在内部访问,因此可能是放大问题。

我在 amplify repo 上打开了问题。

Unable to access dispatch from useContext from components wrapped withAuthenticator

解决方法

我认为有些事情可能是潜在问题。

主要问题是您的 Context 的值。创建上下文时,其值是一个状态 (createContext(initialState))。但是,当您将 value 传递给 Context.Provider 时,您将给它一个包含状态和调度函数 (value={[state,dispatch]}) 的数组。您需要对上下文中包含的值保持一致。是状态对象还是元组?

您描述的错误似乎是在 Context 之外访问 Provider 时会发生的情况。它会回退初始上下文值,它只是一个状态而不是一个 [state,dispatch] 元组。

您需要将初始值更改为与您期望的值相匹配的值。

const Context = createContext([
  initialState,// state
  () => console.error("Cannot dispatch because Context was used outside of a provider") // dispatch
]);

但您还需要弄清楚为什么 useContext 获取默认值而不是来自 Provider 的值。我不确定接下来的两个问题是否会解决这个问题。

看起来 Profile 组件位于两个不同的 Store 提供程序中。一种在一切之外,一种在 Wrapper 组件内部。这些将有两个单独的状态实例。当同一个上下文有两个提供者时,React 使用内部的一个。因此,您从 Profile 分派的任何操作都不会更新 Store 的外部版本。

您在 Context 组件中使用 Store 变量之后创建它。你应该换个顺序。