React Router onEnter未按预期工作

React Router onEnter not working as intended

本文关键字:工作 Router onEnter React      更新时间:2023-09-26

我正在构建一个基本的react登录应用程序,用于教育目的,并使用react路由器的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。我能做什么??

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

  1. 编写一个函数,将道具从实际组件复制到包装器

HoistNonReactStatistics.tsx或jsx(我使用typescript(

    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不允许直接包装组件,因为我没有声明包装函数来接受参数

    export const requireHellow = HelloWrapper();

    1. 现在用函数扭曲任何组件,我在导出时使用过它,但你也可以在Route的组件道具中进行

    export default requireHellow(SomeComponent);

现在,每当你使用这个SomeComponent,并且它将sayHello道具设置为true时,它就会渲染Hello,否则就会渲染实际的组件

<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>

)