我应该在哪里放置重定向代码?

时间:2017-02-21 18:58:05

标签: reactjs react-router

我有一个表示页面的React组件。用户永远不应该到达页面,除非他们有一些状态。如果缺少状态,我写了以下内容让react-router重定向用户:

class BoxScreen extends Component {

  constructor(props) {
    super(props);

    if (Object.keys(this.props.boxState.current).length === 0) {
      browserHistory.push('/secured/find')
    }

然后我收到这条消息:

  

warning.js:36警告:setState(...):无法在现有状态转换期间更新(例如在render或其他组件的构造函数中)。渲染方法应该是道具和状态的纯函数;构造函数副作用是反模式,但可以移动到componentWillMount

好的,我将我的重定向代码移到componentWillMount

class BoxScreen extends Component {
   ...

   componentWillMount() {
    if (Object.keys(this.props.boxState.current).length === 0) {
      browserHistory.push('/secured/find')
    }
   }

   render() {
    // Don't want this executed or else I'll need to pollute it with null guards...
   }
}

然而,问题在于上述内容并未阻止render被调用,这绝对不是必需的。放置这个的最合适的位置在哪里,我可以使组件渲染短路并执行重定向?

3 个答案:

答案 0 :(得分:1)

您可以使用react-router的onEnter道具来实现这一目标:

function checkAuthenticated(nextState, replace) {
  if (!SOME_CONDITION) {
    replace('/secured/find')
  }
}

<Route ... onEnter={checkAuthenticated} />

但我相信你不能以这种方式访问​​组件道具。您必须以其他方式跟踪状态。如果您使用的是Redux,我相信您可以使用redux-router来获取商店。

您可以查看Enter/leave hooks documentation

答案 1 :(得分:1)

只需在渲染中使用react-router的{​​{1}}组件来实现它,我正在使用v4,因此我将为您提供与之兼容的解决方案。

<Redirect/>

import {Redirect} from 'react-router-dom'; class BoxScreen extends Component { ... render() { return this.props.condition ? <ActualComponent /> : <Redirect to="/someGuardLink">; } } 替换为您的组件JSX,是的,这应该可行。您的组件仍然会挂载和渲染,但之后它会将您重定向到其他链接,而不会发现它的任何影响。这是正式的做法。

答案 2 :(得分:0)

扩展smishr4的内容:

  1. 在化简器中对象具有默认状态。例如,我的ID初始状态为:

ID: -1

  1. 确保已将对象从状态映射到道具。

function mapStateToProps(state, ownProps) {
    return {
        ID: state.ID,       
    }
}

  1. 在从React.Component扩展的任何内容上,在componentWillMount()函数中编写一个if条件-以便在加载页面之前发生这种情况。如果未定义.ID字段(最初始终为true),并且在化简器(-1)中将其设置为初始状态之后,此特殊功能会将我带回到首页。

    componentWillMount() {
        {
            if (this.props.ID != -1 && this.props.ID != undefined) {
                this.props.loadYourDataFromAPIGivenID(this.props.ID);
            }
            else {
                this.props.history.push('/');
            }
        }
    }

有更好的方法吗?大概。您也许可以直接在路由器内进行阻塞,但这是一个很好的解决方法。

您也可以直接使用this.state ,但是this.props使用起来更安全。