如何在没有组件闪烁的情况下基于API的数据重新路由-React/Redux



我正在编写一个小型待办事项应用程序,在根据后端数据重新路由用户时遇到问题。该应用程序正在使用:

  • express-session创建服务器端用户会话
  • connect-mongodb-session存储会话数据
  • 用于应用程序状态管理的react-redux

当用户登录时,名为isLoggedInUser模型属性将设置为true。该值用于将用户重定向到LandingPage组件,在那里他们可以创建新的待办事项。这很好,但问题是,如果刷新登录页,则在LandingPage呈现之前,isLoggedIn的值尚未从后端到达。这会导致用户被重新路由到登录页面,然后数据到达,然后他们再次被重新路由至登录页面。

登录页面"闪烁"是非常烦人的,我找不到任何方法来绕过它。我试着在localStorage中存储一个布尔值isLoggedIn,效果很好,但这肯定不能解决使用服务器端会话的问题?

以下是我的代码片段,谢谢

App.js

import { getUser } from "./redux/actions/auth";
const App = withRouter(({ user, data }) => {
useEffect(() => {
store.dispatch(getUser()); // user data loaded every time app re-renders
}, []);
return (
<Provider store={store}>
<Router>
<div className='my-app'>
<Switch>
<Route exact path='/login' component={Login} />
<Private
isLoggedIn={isLoggedIn}
path='/landing'
component={LandingPage}
/>
</Switch>
</div>
</Router>
</Provider>
);
const Private = ({ isLoggedIn, component: Component, ...rest }) => {
return (
<Route
{...rest}
render={props =>
isLoggedIn ? (
<Component {...props} />
) : (
// I think the problem is here - because isLoggedIn is not available from the backend 
// call yet, so login page gets rendered before the data arrives
<Redirect to='/login' {...props} /> 
)
}
/>
);
};

Login.js

render() {
const { user } = this.props;
if (user.isLoggedIn) return <Redirect to='/landing' />; // user sent to landing if they are logged in
return (... login form jsx)
}
Login.propTypes = {
user: PropTypes.object
};
const mapStateToProps = state => ({
user: state.auth.user
});
export default connect(mapStateToProps)(Login);

getUser.js

export const getUser = () => async dispatch => {
try {
const response = await axios.get("/api/user");
dispatch({
type: LOADED_USER,
payload: response.data
});
} catch (error) {
dispatch({
type: LOAD_USER_FAILED
});
}
};

getUserReducer.js

const initialState = {
user: {}
};
export default function(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case LOGIN_SUCCEEDED:
case LOADED_USER:
return {
...state,
user: payload
};
case LOGIN_FAILED:
case LOAD_USER_FAILED:
return {
...state,
user: {}
};
default:
return state;
}
}

所以有几种方法可以做到这一点。一种方法是创建一个经过身份验证的路由,其唯一目的是验证会话cookie,例如/me

如果用户以前登录过,则浏览器应具有作为cookie的有效会话。这意味着CCD_ 13可以用200。如果会话已过期,那么您将获得401。在401的情况下,您只需重定向回登录页面。

有很多方法可以传达这种情况也发生在用户身上。一种方法是像您已经做的那样在本地存储中保存一些状态,并假设用户可以导航到登录页。无论如何都不会加载任何敏感数据,因为数据应该位于经过身份验证的端点之后。

在任何401的情况下,你可以重定向到登录,或者向用户显示一个错误,说"看起来你的会话已经过期,点击这里重新登录。"。

相关内容

  • 没有找到相关文章

最新更新