路线授权HOC导致儿童重新安装3次

问题描述 投票:1回答:2

我正在使用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);
}

有任何想法吗?

reactjs redux react-router react-redux
2个回答
2
投票

这个问题可能已经有一段时间了,但我刚遇到同样的问题。

最后我发现我的HOC功能实际上是在每次路线改变时调用的。

对我有帮助的是在初始化时只创建一次授权组件:

const AuthorisedDashboard = requireLogin(Dashboard);

然后才使用它

<Route path="/dashboard" component={AuthorisedDashboard} />

或者,你知道,我猜你可以导出已经应用了HOC功能的组件,只要它只在授权模式下使用过......


0
投票

我不确定这会对重新渲染问题产生影响,但是你的代码感觉不对。

首先,你似乎有两个真实来源,你的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);
}
© www.soinside.com 2019 - 2024. All rights reserved.