如何使用 Context API 访问状态

Posted

技术标签:

【中文标题】如何使用 Context API 访问状态【英文标题】:How to access state with Context API 【发布时间】:2019-09-11 16:18:24 【问题描述】:

我在 React 应用程序中使用上下文 API 进行状态管理,我正在寻找一种方法来从我的 Provider 类访问无状态函数中的状态。

我熟悉在 render() 中围绕 JSX 包装 Consumer 标签,但在这种情况下,我不会返回任何 JSX

app.js

export default class App extends Component 
  render() 
    return (
      <BrowserRouter>
        <Provider>
            <Header />
            <Switch>
              <PrivateRoute path='/test' component=test />
            </Switch>
        </Provider>
      </BrowserRouter>
    );
  ;
;

/context/index.js(提供者类)

import React,  Component  from 'react';
import axios from 'axios';
import withRouter from 'react-router';

const AuthContext = React.createContext();

class Provider extends Component 

  state =
    firstName: '',
    lastName:'',
    emailAddress: '',
    password: '',
    signedIn: false,
  ;

  render()
    return (
      <AuthContext.Provider value = 
        user: ...this.state,
      >
        this.props.children
      </AuthContext.Provider>
    );
  ;
;

export default withRouter(Provider);
export const Consumer = AuthContext.Consumer;

PrivateRoute.js

import React from 'react';
import  Route  from 'react-router-dom';

const PrivateRoute = ( component: Component, ...rest) => 
  <Route ...rest render = () => (

  /* I NEED TO CHECK IF USER IS SIGNED IN. HOW DO I ACCESS this.state.signedIn from within the Provider class? */

  ) />


export default PrivateRoute

我正在开发一个需要在访问路由之前进行身份验证的组件,但首先我需要弄清楚如何将状态从 Provider 类拉到 PrivateRoute.js 中

【问题讨论】:

这里是react context APILink to related question的清晰结构的更好实现 【参考方案1】:

您可以将PrivateRoute 包装在另一个匿名函数中,该函数使用上下文作为渲染道具,并通过道具将其传递给 PrivateRoute

import React from 'react';
import  Route  from 'react-router-dom';

const PrivateRoute = ( component: Component, context, ...rest) => 
  return <Route ...rest render = () => (

     /* use `context.signedIn` from within the Provider class? */

  ) />


export default () => <Consumer>(context) => <PrivateRoute context=context /></Consumer>

或者如果你使用的是v16.8.0或以上的react,你可以使用useContext hook

import React,  useContext  from 'react';
import  Route  from 'react-router-dom';

const PrivateRoute = ( component: Component, context, ...rest) =>  
  const context = useContext(AuthContext);
  return <Route ...rest render = () => (

     /* use `context.signedIn` from within the Provider class? */

  ) />

【讨论】:

无法让您的第一个解决方案发挥作用。如果 context.signedIn 为假,它会重定向到没有问题的登录页面,但是一旦我登录,在呈现到我想要的组件时就会出现错误。我在The error occured in &lt;Context.Provider&gt;" "Warning: React.createElement: type is invalid --expected a string or a class/function but got undefined. Likely forgot to export your component from the file its defined in or mixed up default and named imports 中遇到的控制台错误您的第二个解决方案(useContext)没有问题

以上是关于如何使用 Context API 访问状态的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 React Context API 跨多个 Routes 拥有状态?

在组件之间路由时如何保持 React 新的 Context API 状态?

如何使用 React Hooks 和 Context API 正确地将来自 useEffect 内部调用的多个端点的数据添加到状态对象?

如何访问反应Context.Provider值中的另一个函数?

如何使用 Context API 将单个 Socket IO 实例传递给页面?

React Native 状态管理(Redux、Context API 或 Graphql)