React Router onEnter未按预期工作

时间:2016-10-19 12:10:37

标签: javascript reactjs react-router

我正在构建一个用于教育目的的基本反应登录应用程序,并验证我正在使用React-router的onEnter道具功能的路线

import axios from 'axios';    

var Authentication = (nextState, replace, callback) => {
    axios.get('/api/getuser')
    .then((res) => {
        if(res.data != '') {
          replace('account/wall')
        }
        callback()
    })
    .catch((err) => {
        callback()
    })

}

export default (
  <Route component={Root}  >
      <Route path='/' component={Home} onEnter={Authentication}/>
      <Route path='/login' component={Login} onEnter={Authentication}/> 
      <Route path='/signup' component={Registration} onEnter={Authentication}/> 
      <Route path='/account/wall' component={Wall}/>
      <Route path='*' component={Notfound} />
  </Route>

);

一切都按预期工作但是我不知道为什么路由器将Home组件呈现为闪烁秒,然后在登录后尝试/account/wall路由时将路由替换为/?如果我在登录后尝试/login/signup,也会发生同样的事情。无论如何都要修复此行为?

我已经尝试通过在componentWillMount方法中验证用户来解决这个问题(这不是我想的反应方式),在检查用户时渲染空<div>但是也会在第二次闪烁时呈现空白页面而不是正确的方法。

所以我只想渲染/account/wall如果用户在没有任何中间件渲染的情况下进行身份验证。我该怎么办?

2 个答案:

答案 0 :(得分:1)

我不能正确的例子,因为每个人的实现都有所不同,但是我要说明一个包装任何组件的HelloWrapper组件示例,如果它接收到sayHello prop为true,它将呈现Hello而不是实际组件,可以检查登录道具并重定向或显示登录组件..在你的情况下。

  1. 编写一个函数将道具从实际组件复制到包装器
  2. HoistNonReactStatistics.tsx或jsx(我使用的是打字稿)

        const REACT_STATICS = {
        childContextTypes: true,
        contextTypes: true,
        defaultProps: true,
        displayName: true,
        getDefaultProps: true,
        mixins: true,
        propTypes: true,
        type: true
        };
    
        const KNOWN_STATICS = {
        name: true,
        length: true,
        prototype: true,
        caller: true,
        arguments: true,
        arity: true
        };
    
        export default function hoistStatics(targetComponent, sourceComponent) {
        var keys = Object.getOwnPropertyNames(sourceComponent);
        for (var i = 0; i < keys.length; ++i) {
          const key = keys[i];
          if (!REACT_STATICS[key] && !KNOWN_STATICS[key]) {
            try {
              targetComponent[key] = sourceComponent[key];
            } catch (error) {}
          }
        }
        return targetComponent;
        }
    
    1. 写包装函数,它将返回包装组件

       import * as React from 'react';
       import HoistNonReactStatistics from "./HoistNonReactStatistics"
       export function HelloWrapper(){
      
       return function HellowWrapComponent(DecoratedComponent) {
      
       class WrappendComponent extends React.Component<{sayHello?:boolean},{}>{
          constructor(props){
            super(props);
          }
          componentWillMount(){
           /** do some login check here and redirect if required **/
           }
          componentWillReceiveProps(nextProps){
           /** do some login check here and redirect if required **/
           }
         render(){
           if(this.props.sayHello){
             return <div>Hello</div>
           }else{
             return <DecoratedComponent />
           }
         }
       }
       /** if you use redux then also apply the connect method on return component so it get access to required auth reducer data**/
       return HoistNonReactStatistics(WrappendComponent,DecoratedComponent);
       }
      }
      
      1. 创建一个const(不确定jsx是否需要此步骤,但是typescript不允许直接包装组件,因为我没有声明包装函数接受参数
      2. export const requireHellow = HelloWrapper();

        1. 现在扭曲任何具有功能的组件,我在导出时使用它,但你也可以在Route的组件prop中执行它
        2. export default requireHellow(SomeComponent);

          现在每当你使用这个SomeComponent并且 sayHello prop to true 时它将呈现Hello,否则渲染实际的组件

答案 1 :(得分:0)

<code>function requireAuth(nextState, replace,callback){
     var data = {
         token: store.getState().student.token,
         email: store.getState().student.email}
     makeUserRequest('post', data, '/api/auth')
     .then((res)=>{
            if (!res.data.success) {
                    replace({ nextPathname: nextState.location.pathname },  nextState.location.query)
            }
            callback()
     })
 }

return(
    <Router history={browserHistory}>
<Route path='/' component={app}>
  <IndexRoute  component={login} />
        <Route path='home' component={home} />
  <Route path='login' component={login} />
  <Route path='profile' component={profile} onEnter={requireAuth} />
</Route>

    )