Как получить доступ к состоянию с помощью Context API

Я использую контекстный API для управления состоянием в приложении React, и я ищу способ получить доступ к состоянию в функции без сохранения состояния из моего класса Provider.

Я знаком с оберткой тегов Consumer вокруг JSX внутри render (), но в этом случае я не возвращаю 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


person learnerforlife    schedule 22.04.2019    source источник


Ответы (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

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? */

  )} />
}
person Shubham Khatri    schedule 22.04.2019
comment
Не удалось заставить ваше первое решение работать. Если context.signedIn был ложным, он перенаправлялся на страницу входа без проблем, но как только я вошел в систему, при рендеринге в желаемый компонент возникли ошибки. Ошибки консоли, которые я получил в соответствии со строками The error occured in <Context.Provider>" "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) работает без проблем. - person learnerforlife; 23.04.2019