繁体   English   中英

在调度一个动作后,React 不能使用更新的 Redux state

[英]React cannot use the updated Redux state after having dispatched an action

我对 React 和 Redux 比较陌生,并通过我的个人项目学习它们。

这里的问题是执行rest.dispatch(actions.isValidUser(json)) isAuthed使用更新的 Redux state。 据我所知,Redux state 是由动作更新的。 (但我没有看到在更新后调用了connect() ......我不知道这是否与这个问题有关。)

我还尝试在我的操作文件中使用 Redux-thunk 从 API 端点获取数据并使用 useEffect(),但它没有解决问题。 你能帮帮我吗?

先感谢您。

**ProtedtedRoute.jsx**

import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import * as actions from '../actions/actions';


function ProtectedRoute({ component: Component, isAuthed, ...rest }) {
  
  async function verifyUser() {
     // checking if a user is valid by checking JWT
      const res = await fetch(ENDPOINT, reqOptions);
    if (res.status === 200) {
      const json = await res.json();
      rest.dispatch(actions.isValidUser(json));
    } else {
      // failure handling
    };
  };

  verifyUser();

  return (
    <Route
      {...rest}
      render={(props) => isAuthed == true ? <Component {...props} /> : <Redirect to={{ pathname: '/login', state: { from: props.location } }} />}
    />
  );
};


export default connect(state => {
  return {
    isAuthed: state.isAuthenticated
  }
})(ProtectedRoute);

**reducer.js**
const initState = {
    data: {},
    // when a user is valid, it will be ```true```
    isAuthenticated: false
}


**App.js**

function App() {

  return (
    <Provider store={store}>
        <BrowserRouter>
          <div>
            <div className="content">
              <Switch>
                <Route exact path="/" component={Home} />
                <PublicRoute path="/login" component={LogIn} />
                <PublicRoute path="/signup" component={SignUp} />
                <ProtectedRoute path="/dashboard" component={Dashboard} />
              </Switch>
              ...


**Login.jsx**

 const res = await fetch(ENDPOINT, { reqOptions});
        if (res.status === 200) {
            props.history.push('/dashboard');
        else{
            // error handling
        }

您不想要像verifyUser(); 只是漂浮在组件中。 它需要在useEffect挂钩内。

您的Login组件会在您重定向到Dashboard之前获取端点,因此您无需再次获取端点即可通过PrivateRoute访问Dashboard

您可以更改您的initialState以包括isAuthenticated: undefined ,如“我们不知道它们是否经过身份验证,因为我们尚未检查。”

然后在PrivateRoute中,如果isAuthed的值是undefined意味着我们还没有检查,我们只需要调用verifyUser 如果它是truefalse ,我们只使用现有的值。

我们的 aysnc 流程仍然存在一些问题,因为我们不想在verifyUser完成之前RedirectPrivateRoute 为此,我们可以有条件地呈现在等待凭据时显示的加载 state。

我不知道这是最优雅的解决方案,但它应该可以工作

function ProtectedRoute({ component: Component, isAuthed, ...rest }) {

  async function verifyUser() {
    // checking if a user is valid by checking JWT
    const res = await fetch(ENDPOINT, reqOptions);
    if (res.status === 200) {
      const json = await res.json();
      rest.dispatch(actions.isValidUser(json));
    } else {
      // failure handling
    }
  }

  useEffect(() => {
    if (isAuthed === undefined) {
      verifyUser();
    }
  }, [isAuthed]); //re-run when isAuthed changes

  return (
    <Route
      {...rest}
      render={(props) =>
        isAuthed === undefined ? (
          <Loading />
        ) : isAuthed === true ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{ pathname: "/login", state: { from: props.location } }}
          />
        )
      }
    />
  );
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM