ReactJs: Как правильно обращаться к данным о состоянии в компоненте root, где реализована связь между React и Redux? - PullRequest
0 голосов
/ 14 февраля 2020

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Эта ошибка упоминалась ранее в stackoverflow, но у меня другой случай.
У меня была проблема с логином пользователя, которую я объяснил в этом stackOverFlow вопросе . Я приглашаю вас на go и быстро взгляните.
Итак, как я уже упоминал в этом вопросе в моем файле root, у меня есть это:

Приложение. js

class App extends Component {
  render() {
    const authLinks = (
      <Switch>
        <Route
          exact
          path="/"
          name="Login Page"
          render={props => <Login {...props} />}
        />
        <Route
          exact
          path="/404"
          name="Page 404"
          render={props => <Page404 {...props} />}
        />
        <Route
          exact
          path="/500"
          name="Page 500"
          render={props => <Page500 {...props} />}
        />
        <Route
          path="/home"
          name="Home"
          render={props => <DefaultLayout {...props} />}
        />
      </Switch>
    );

    const guestLinks = (
      <Switch>
        <Route
          exact
          path="/"
          name="Login Page"
          render={props => <Login {...props} />}
        />
        <Route
          exact 
          path="/register"
          name="Register Page"
          render={props => <Register {...props} />}
        />
        <Route
          exact
          path="/404"
          name="Page 404"
          render={props => <Page404 {...props} />}
        />
        <Route
          exact
          path="/500"
          name="Page 500"
          render={props => <Page500 {...props} />}
        />
      </Switch>
    );

    const currentState = store.getState();
    console.log(
      "currentState.auth.isAuthenticated: ",
      currentState.auth.isAuthenticated
    );
    return (
      <Provider store={store}>
        <HashRouter>
          <React.Suspense fallback={loading()}>
            {console.log(currentState.auth.isAuthenticated)}
            {/* TODO: Not sure if this always works. If after the user logsin he gets a blank page and he has to reload to be redirected to home then
            this way of routing may need to modified */}
            {currentState.auth.isAuthenticated ? authLinks : guestLinks}
          </React.Suspense>
        </HashRouter>
      </Provider>
    );
  }
}  

Мне сказали, что я получаю доступ к состоянию isAuthenticated неправильно:

 {currentState.auth.isAuthenticated ? authLinks : guestLinks}  

Мне нужно получить к нему доступ с помощью connect () . Это было первое, что я попробовал. Это не сработало. Но я воспользовался их советом и попробовал снова:

class App extends Component {
  render() {
    const authLinks = (
      <Switch>
        <Route
          exact
          path="/"
          name="Login Page"
          render={props => <Login {...props} />}
        />
        <Route
          exact
          path="/404"
          name="Page 404"
          render={props => <Page404 {...props} />}
        />
        <Route
          exact
          path="/500"
          name="Page 500"
          render={props => <Page500 {...props} />}
        />
        <Route
          path="/home"
          name="Home"
          render={props => <DefaultLayout {...props} />}
        />
      </Switch>
    );

    const guestLinks = (
      <Switch>
        <Route
          exact
          path="/"
          name="Login Page"
          render={props => <Login {...props} />}
        />
        <Route
          exact
          path="/register"
          name="Register Page"
          render={props => <Register {...props} />}
        />
        <Route
          exact
          path="/404"
          name="Page 404"
          render={props => <Page404 {...props} />}
        />
        <Route
          exact
          path="/500"
          name="Page 500"
          render={props => <Page500 {...props} />}
        />
      </Switch>
    );

    const currentState = store.getState();
    console.log(
      "currentState.auth.isAuthenticated: ",
      currentState.auth.isAuthenticated
    );
    return (
      <Provider store={store}>
        <HashRouter>
          <React.Suspense fallback={loading()}>
            {console.log(currentState.auth.isAuthenticated)}
            {/* TODO: Not sure if this always works. If after the user logsin he gets a blank page and he has to reload to be redirected to home then
            this way of routing may need to modified */}
            {/* {currentState.auth.isAuthenticated ? authLinks : guestLinks} */}
            {this.props.auth.isAuthenticated ? authLinks : guestLinks}
          </React.Suspense>
        </HashRouter>
      </Provider>
    );
  }
}

App.propTypes = {
  auth: PropTypes.object.isRequired,
  errors: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
  auth: state.auth,
  errors: state.errors
});
export default connect(mapStateToProps, null)(withRouter(App));

, что дает указанную выше ошибку:

Could not find "store" in the context of "Connect(withRouter(App))". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(withRouter(App)) in connect options.

, что имеет смысл, так как хранилище пропущено root компонент приложение. js через роутер. Таким образом, к состоянию приложения нельзя обращаться так же, как к нему обращаются в childComponents через connect . Поэтому у меня есть два вопроса:
ВОПРОС 1: Почему я получаю эту ошибку?
ВОПРОС 2: Как правильно получить доступ к данным состояния внутри root компонент, где реализована связь между редуксом и реакцией?

Ответы [ 2 ]

0 голосов
/ 14 февраля 2020

ОТВЕТ 1 : Я думаю, что вы должны использовать "connect" в компоненте, называемом внутри Provider. docs говорит:

Could not find "store" in either the context or props
If you have context issues,

Make sure you don’t have a duplicate instance of React on the page.
Make sure you didn’t forget to wrap your root or some other ancestor component in <Provider>.
Make sure you’re running the latest versions of React and React Redux.
/*Into App.js*/
return (
      <Provider store={store}>
        <HashRouter>
          <React.Suspense fallback={loading()}>
            <ConnectedComponent>
          </React.Suspense>
        </HashRouter>
      </Provider>
    );

    /*ConnectedComponent.js*/
    class ConnectedComponent extends React
    {
      render(){
      {
        /* move all your routing and app code Here*/
      }
    }

    //call connect on your ConnectedComponent
    export connect(mapStateToProps, null)(ConnectedComponent)

Я также думаю, что вам не нужно использовать withRouter, потому что кажется, что вам не нужны реквизиты ReactRouter (матч, история, location) в компоненте вашего приложения.

Здесь вы можете увидеть, когда вам следует использовать withRouter : https://reacttraining.com/react-router/web/api/withRouter

ОТВЕТ 2 : функция connect () выполняет работу по подключению хранилища Redux к вашему дереву компонентов React. Вы всегда должны получать доступ к данным хранилища через объект props.

0 голосов
/ 14 февраля 2020

ВОПРОС 1:

Я полагаю, вы должны сначала обернуть withRouter.

Попробуйте это:

import { connect } from "react-redux";
import { withRouter } from "react-router";

export default withRouter(connect(mapStateToProps, null)(App));

ВОПРОС 2: Вы отображаете состояние на props, поэтому правильный способ доступа к auth из вашего состояния в вашем компоненте - this.props.auth

Попробуйте console.log (this.props) в вашем рендере, и вы поймете, что я имею в виду. Также проверьте документы на https://react-redux.js.org/api/connect

Надеюсь, это поможет

...