我使用react-redux来管理状态,使用axios来调用API。
我的默认状态:
const defaultState = {
isLoading: true,
isAuthenticated: false,
authUser: {}
}
一旦API的登录调用成功运行,isLoading
和authUser
都会更新。
在userProfile组件中,我使用以下命令从存储中获取登录用户的ID:
const authUser = useSelector(state => state.authentication.authUser);
const user = users.getUser(authUser.id);
console.log(authUser);
authUser
在页面加载时总是空的,但延迟了一秒钟,它再次打印,这次是状态内容。
我在自定义PrivateRoute
组件后面有userProfile组件:
const PrivateRoute = ({ component: Component, ...rest }) => {
const authentication = useSelector(state => state.authentication);
return (
<Route
{...rest}
render={props =>
authentication.isAuthenticated ? (
<Component {...props} />
) : (
authentication.isLoading ? 'loading...' :
<Redirect to={{ pathname: '/login', state: { from: props.location } }} />
)
}
/>
)
};
loading...
文本在组件赶上之前显示,然后两个控制台日志一个接一个地出现。第一个为空,第二个为data.
我在这里错过了什么?异步的东西快把我逼疯了!
有了这个私有路由的实现,你可以保存用户的当前路径,让用户在再次登录后继续他的进程
import React from 'react';
import { Login } from '../../pageComponents';
import { useSelector } from 'react-redux';
const PrivateRoute = (Component) => {
const Auth = (props) => {
const { isLoggedIn } = useSelector((state) => state.user);
// Login data added to props via redux-store (or use react context for example)
// If user is not logged in, return login componentc
if (!isLoggedIn) {
return <Login />;
}
// If user is logged in, return original component
return <Component {...props} />;
};
// Copy getInitial props so it will run as well
if (Component.getInitialProps) {
Auth.getInitialProps = Component.getInitialProps;
}
return Auth;
};
export default PrivateRoute;
然后在你想要私有路由的每个页面使用它,如下所示
const myPrivateRoute = () => {
return (
<h1>Hello world</h1>
)
}
export default PrivateRoute(myPrivateRoute)
所以像这样创建组件并从本地存储或cookie加载最后一节然后验证并发送到redux存储然后你可以记住log
import { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import axios from "axios";
import * as globalActions from "../../../store/actions/globalAction";
import * as userAction from "../../../store/actions/userAction";
const StorageManagment = () => {
const dispatch = useDispatch();
/* ----------------------------------- listening to token changes ----------------------------------- */
useEffect(() => {
dispatch(userAction.loadCart());
}, []);
useEffect(async () => {
try {
if (window)
await checkLocalDataWithRedux()
.then((data) => {
const { userDTO, token } = data;
dispatch(userAction.loginUser(token, userDTO));
})
.catch((e) => {
console.log(e);
dispatch(userAction.logOutUser());
});
} catch (e) {
throw e;
}
}, []);
function checkLocalDataWithRedux() {
return new Promise((resolve, reject) => {
try {
/* -------- read user data from localStorage and set into redux store ------- */
const { userDTO, token } = localStorage;
if (userDTO && token) {
resolve({ token: token, userDTO: JSON.parse(userDTO) });
} else logOutUser();
} catch (e) {
reject();
}
});
}
function logOutUser() {
dispatch(userAction.logOutUser());
}
return null;
};
export default StorageManagment;
然后加载到app.jsx文件
app.js
render() {
return (
<React.Fragment>
<Provider store={store}>
<ErrorBoundary>
<StorageManagment />
<DefaultLayout>
<Application {...this.props} />
</DefaultLayout>
</ErrorBoundary>
</Provider>
</React.Fragment>
);
}