javascript - 如何在 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(...)(...)' 因为它是未定义的。有人可以指出我是什么或我要去哪里错了。谢谢。
解决方案
您不能在提供它的同一组件中使用上下文。为了解决这个问题,创建另一个新组件,它是 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 />
。然后在应用程序内部,您可以像尝试做的那样使用上下文。
推荐阅读
- c++ - 在 Windows 10 上使用 Clang for ARM 链接 cpp
- git - 与 oneline 相比,带有 tformat 的 git log 中的额外换行符
- android - Delphi TMapView 禁用自动缩放
- ruby-on-rails - 通过 API 编辑 Google 日历事件符合带有外部链接的 URI
- angular - 如何在无限滚动功能中获取搜索栏的值
- python - 修复超过 180 度限制的二面角以创建平滑曲线
- java - 我使用了 Jersey bean 验证,我已经传递了一条消息,根据一些文章,如果验证失败,该消息应该显示该消息
- android - Android 公共资源作为具有模块化结构的 Android 应用程序的库
- .net - MS Graph UserPrincipalName 与 OID 返回
- github - 引用 Github Actions 构建的工件