React 在调度一个动作后不能使用更新的 Redux 状态
React cannot use the updated Redux state after having dispatched an action
我对 React 和 Redux 比较陌生,通过我的个人项目学习它们。
这里的问题是 isAuthed
在 rest.dispatch(actions.isValidUser(json))
执行后无法使用更新后的 Redux 状态。据我所知,Redux 状态由操作更新。 (但是我没有看到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
之前获取端点,因此您不需要 再次 获取端点来访问Dashboard
到 PrivateRoute
.
您可以更改 initialState
以包含 isAuthenticated: undefined
,如“我们不知道他们是否经过身份验证,因为我们尚未检查。”
然后在PrivateRoute
中,如果isAuthed
的值为undefined
,我们只需要调用verifyUser
,也就是说我们还没有检查。如果它是 true
或 false
我们就使用现有的值。
我们仍然对 aysnc 流程有一些问题,因为我们不想在 verifyUser
完成之前 Redirect
关闭 PrivateRoute
。为此,我们可以有条件地呈现在等待凭据时显示的加载状态。
我不知道这是最优雅的解决方案,但它应该可行
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 } }}
/>
)
}
/>
);
}
我对 React 和 Redux 比较陌生,通过我的个人项目学习它们。
这里的问题是 isAuthed
在 rest.dispatch(actions.isValidUser(json))
执行后无法使用更新后的 Redux 状态。据我所知,Redux 状态由操作更新。 (但是我没有看到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
之前获取端点,因此您不需要 再次 获取端点来访问Dashboard
到 PrivateRoute
.
您可以更改 initialState
以包含 isAuthenticated: undefined
,如“我们不知道他们是否经过身份验证,因为我们尚未检查。”
然后在PrivateRoute
中,如果isAuthed
的值为undefined
,我们只需要调用verifyUser
,也就是说我们还没有检查。如果它是 true
或 false
我们就使用现有的值。
我们仍然对 aysnc 流程有一些问题,因为我们不想在 verifyUser
完成之前 Redirect
关闭 PrivateRoute
。为此,我们可以有条件地呈现在等待凭据时显示的加载状态。
我不知道这是最优雅的解决方案,但它应该可行
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 } }}
/>
)
}
/>
);
}