我正在使用HOC组件来限制对未登录用户的路由访问。当从URL直接访问此路由时(在应用程序首次加载时),此HOC在安装或重新呈现时重新安装子组件的问题。例如,我在did mount
组件中有3倍的PaperWorkProgress
。
路线定义:
<Route path="/paperwork/progress" component={RequireAuth(PaperWorkProgress)}/>
这里的HOC代码:
import React, {Component} from 'react';
import {connect} from 'react-redux';
export default function(ComposedComponent) {
class Authentication extends Component {
// check if token exists in storage
componentWillMount() {
const token = localStorage.getItem('token');
if (!token) {
const {pathname, search} = this.props.location;
this.props.history.push({
pathname: '/signin',
search: `?redirect_to=${pathname}${search}`,
});
}
}
// additional check
componentWillUpdate(nextProps) {
if (!nextProps.loggedIn) {
const {pathname, search} = this.props.location;
this.props.history.push({
pathname: '/signin',
search: `?redirect_to=${pathname}${search}`,
});
}
}
render() {
return <ComposedComponent {...this.props} />;
}
}
function mapStateToProps(state) {
return {loggedIn: state.session.loggedIn};
}
return connect(mapStateToProps)(Authentication);
}
有任何想法吗?
这个问题可能已经有一段时间了,但我刚遇到同样的问题。
最后我发现我的HOC功能实际上是在每次路线改变时调用的。
对我有帮助的是在初始化时只创建一次授权组件:
const AuthorisedDashboard = requireLogin(Dashboard);
然后才使用它
<Route path="/dashboard" component={AuthorisedDashboard} />
或者,你知道,我猜你可以导出已经应用了HOC功能的组件,只要它只在授权模式下使用过......
我不确定这会对重新渲染问题产生影响,但是你的代码感觉不对。
首先,你似乎有两个真实来源,你的redux商店和localStorage,这使事情变得复杂。如果要从以前的导航信息“保湿”商店,则应使用createStore“preloadedState”参数,而不是每次在组件中进行检查。 Cf Redux doc和这个视频来自Redux自己Video for persisting and rehydrating State的创造者。一旦您的州只来自您的商店,它开始变得更加简单。
第二,
当你推送到组件内部的历史对象时,感觉就像你正在改变组件自己的道具(因为历史是道具)。这对我来说很奇怪,可能是你问题的根源。
为什么不在渲染方法中使用Redirect组件呢? cf React router docs。该组件看起来像这样(显然你也需要更改你的登录组件,就像在文档中一样)
import React, { Component } from "react";
import { connect } from "react-redux";
import { Redirect } from "react-router-dom";
export default function(ComposedComponent) {
class Authentication extends Component {
render() {
return !this.props.loggedIn ? (
<Redirect
to={{
pathname: "/login",
state: { from: this.props.location }
}}
{...this.props}
/>
) : (
<ComposedComponent {...this.props} />
);
}
}
function mapStateToProps(state, ownProps) {
return { loggedIn: state.session.loggedIn, ...ownProps };
}
return connect(mapStateToProps)(Authentication);
}