首页 > 解决方案 > 如何在 react app.js 文件中访问我的上下文 API 状态

问题描述

嗨,我正在使用 Context API 管理我的反应应用程序状态,并且我能够在除 app.js 文件之外的所有文件中解构我的 Context 的状态和功能。

在这里,我创建了一个名为“createDataContext”的可重用文件,以防止在为每个 Context 创建 Context 和 Provider 时编写重复代码。

import React, { createContext, useReducer } from 'react';

export default (reducer, actions, initialState) => {
  const Context = createContext();

  const Provider = ({ children }) => {
    const [state, dispatch] = useReducer(reducer, initialState);

    const boundActions = {};
    for(let key in actions){
      boundActions[key] = actions[key](dispatch);
    }

    return (
      <Context.Provider value={{ state, ...boundActions }}>
        { children }
      </Context.Provider>
    )
  }

  return { Context, Provider }
}

这是我使用 createDataContext 文件的 AuthContext

import createDataContext from "./createDataContext";
import api from '../api/api'

const authReducer = (state, action) => {
  switch(action.type){
    case 'signin':
      return { errorMessage: '', token: action.payload };
    case 'add_error':
      return { ...state, errorMessage: action.payload };
    default:
      return state;
  }
}

const login = dispatch => {
  return async (email, password) => {
    try {
      const res = await api.post('/users/login', { email, password });
      localStorage.setItem('token', res.data.token);
      dispatch({ type: 'signin', payload: res.data.token });
    }catch(err){
      dispatch({ type: 'add_error', payload: 'signin failed' })
    }
  }
}

export const { Context, Provider } = createDataContext(authReducer, { login }, {
  token: null,
  errorMessage: ''
});

我可以在我的页面和组件中使用上下文和析构函数关闭状态和功能,如登录,但无法在我的 app.js 文件中这样做。

import React, { useContext } from 'react';
import Home from './pages/home/Home';
import Login from './pages/login/Login';
import Profile from './pages/profile/Profile';
import Register from './pages/register/Register';
import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom';
import Navbar from './components/navbar/Navbar';
import { Provider as AuthProvider } from './context/AuthContext';
import { Context } from './context/AuthContext';

function App() {
  const { state, login } = useContext(Context);

  return (
    <AuthProvider>
      <Router>
        <Navbar />
        <Switch>
          <Route exact path="/">
            <Home />
          </Route>
          <Route path="/login">
            <Login />
          </Route>
          <Route path="/register">
            <Register />
          </Route>
          <Route path="/profile/:id">
            <Profile />
          </Route>
        </Switch>
      </Router>
    </AuthProvider>
  );
}

export default App;

我收到错误TypeError: Cannot destructure property 'state' of 'Object(...)(...)' 因为它是未定义的。有人可以指出我是什么或我要去哪里错了。谢谢。

标签: javascriptreactjsreact-context

解决方案


您不能在提供它的同一组件中使用上下文。为了解决这个问题,创建另一个新组件,它是 Provider 其余子级的包装器

// AppWrapper.jsx
import React from 'react'
import App from './app'
import { Provider as AuthProvider } from './context/AuthContext'

const AppWrapper = () => {
  return (
    <AuthProvider>
      <App />
    </AuthProvider>
  )
}

default export AppWrapper

然后<AuthProvider>从您的 app.js 组件中删除 ,并在<App />树中调用的任何位置调用<AppWrapper />。然后在应用程序内部,您可以像尝试做的那样使用上下文。


推荐阅读