当前位置: 首页 > 知识库问答 >
问题:

React React-路由器:重定向时替换子组件时重新渲染Navbar组件

金何平
2023-03-14

我在React路由器2.2.1中使用React 15.0.1。我将应用程序用作父组件,它呈现从路由器处理程序传递的子组件。

var App = React.createClass({

    getInitialState(){
        return {
            auth : false
        }
    },

    checkAuth(){
        var self = this;
        $.ajax({
            type : 'GET',
            url : '/auth',
            success : function(res){
                if(res){
                    self.setState({
                        auth : true
                    });
                }else{
                    self.setState({ auth : false});
                }
            }
        });
    },

    render() {
        return(
            <div className="appWrapper">
                <Navbar auth={this.state.auth}/>
                <div className="container">
                    {this.props.children}
                </div>
            </div>
        );
    }
});

这是我的导航栏组件。

var Navbar = React.createClass({

    getInitialState(){
        return{
            user_actions : '' ,
            auth : this.props.auth
        }
    },

    componentDidMount(){
        this.checkAuth();
    },

    componentWillReceiveProps(nextProps){
        this.setState({
            auth : nextProps.auth
        }, function(){
            this.checkAuthState();
        });

        console.log(nextProps.auth);
    },

    checkAuth(){
        var self = this;
        $.ajax({
            type : 'GET',
            url : '/auth',
            success : function(res){
                if(res){
                    self.setState({
                        auth : true
                    });
                }else{
                    self.setState({ auth : false});
                }
                self.checkAuthState();
                console.log(self.state);
            }
        });
    },

    checkAuthState(){

        if(!this.state.auth){
            this.state.user_actions =   <ul className="nav navbar-nav navbar-right">
                                            <li><a href="/login">Login</a></li>
                                            <li><a href="/register">Register</a></li>
                                        </ul>;
            this.setState({
                user_actions : this.state.user_actions
            });
        }

        if(this.state.auth){
            this.state.user_actions =   <ul className="nav navbar-nav navbar-right">
                                            <li><a href="/logout">Logout</a></li>
                                        </ul>;
            this.setState({
                user_actions : this.state.user_actions
            });
        }
    },

    render : function(){
        return (
            <nav className="navbar navbar-default">
                <div className="container">
                    <a href="/" className="navbar-brand">Reactor</a>
                    {this.state.user_actions}
                </div>
            </nav>
        );
    }
});

这些是我的路线处理程序。当用户在路由上着陆时,将对其进行身份验证检查。如果身份验证失败,它们将被重定向到登录路径。

var routes = (
    <Router history={browserHistory}>
        <Route path="/" component={require('./components/app')}>
            <IndexRoute component={require('./components/dashboard/index')} onEnter={Auth.isAuthenticated}/>

            <Route path="/register"
                   component={require('./components/authentication/register')}
                   onEnter={Auth.isNotAuthenticated} />

            <Route path="/login"
                   component={require('./components/authentication/login')}
                   onEnter={Auth.isNotAuthenticated}/>

            <Route path="*"
                   component={require('./components/404/404')}/>
        </Route>
    </Router>
);

当应用程序组件第一次挂载导航栏和子组件时,它会检查身份验证并相应地添加到导航栏的链接。成功登录后,当用户从登录路由重定向到索引路由时,子组件将替换为其他组件,并调用该组件的生命周期方法,但Navbar不会重新呈现。如何重新呈现Navbar组件,使其能够再次检查身份验证并更改为Navbar链接?

共有2个答案

高钱青
2023-03-14

您需要在单独的服务中抽象身份验证逻辑,例如

auth = {
  check() {
    var self = this;
    $.ajax({
      type : 'GET',
      url : '/auth',
      success : function(res){
        if(res){
          onChange(true)
        }else{
          onChange(false);
        }
      }
    });
  },

  onChange() {}
}

然后在你的App组件中你可以做

updateAuth(isLoggedIn) {
  self.setState({auth: isLoggedIn});
}

componentWillMount() {
  auth.onChange = this.updateAuth;
}

在每个需要检查身份验证的路由中,您可以添加onEnter={auth.check}或者您可以将数据存储在本地存储中,以避免每次都调用api。

请参阅使用react-router的auth流的基本示例

华献
2023-03-14

我想通了,我把一个方法从应用程序组件传递给儿童组件。

var App = React.createClass({

    getInitialState(){
        return {
            auth : false
        }
    },

    checkAuth(){
        var self = this;
        $.ajax({
            type : 'GET',
            url : '/auth',
            success : function(res){
                if(res){
                    self.setState({
                        auth : true
                    });
                }else{
                    self.setState({ auth : false});
                }
            }
        });
    },

    updateNavbar(){
        this.checkAuth();
    },

    render() {
        return(
            <div className="appWrapper">
                <Navbar auth={this.state.auth}/>
                <div className="container">
                    {React.cloneElement(this.props.children, {update: this.updateNavbar})}
                </div>
            </div>
        );
    }
});

当子组件(例如登录)对用户进行身份验证时,它调用作为道具传递的更新方法,该方法将重新检查身份验证,并更改应用程序组件的身份验证状态,这将使用新道具在导航栏组件上触发componentWillReceiveProps方法,新道具将更改状态并重新呈现导航栏组件。这就是我想要达到的目标。

var Login    =   React.createClass({
    getInitialState(){
        return {
            user : {email  : '', password : ''},
            auth_redirect : '',
            errors  : {},
            message : ''
        }
    },

    componentWillMount(){...},

    registerFormIsValid : function(){....},

    validateUser : function(){
        var self = this;
        $.ajax({
            type : 'POST',
            url : '/login',
            data : {
                email : this.state.user.email,
                password : this.state.user.password
            },
            success : function(res){
                if(!res.auth){
                    self.setState({
                        message : <Alert message="Invalid Email or Password!"/>
                    });
                }else{
                    self.props.update(); // Update Navbar 
                    self.context.router.push('/');
                }
            }
        });
    },

    Authenticate : function(event){....},

    saveUserState : function(event){...},

    render : function(){
        return (
            <div>
                <div className="login container">
                    <LoginForm
                        user={this.state.user}
                        onChange={this.saveUserState}
                        onSave={this.Authenticate}
                        errors={this.state.errors} />
                    {this.state.message}
                </div>
            </div>
        );
    }
});

现在我可以通过调用this.props.update()从路由处理程序传递的任何子组件更新我的导航栏组件链接。

 类似资料:
  • 我对react还比较陌生,我一直在分解一个web应用程序,并用react组件替换部分。我现在正在开发一个组件,其中包含我创建的几个不同组件。 在新组件中,我在componentDidMount函数中进行API调用,并创建子组件。乍一看,一切看起来都很完美,但当我们在其中一个子组件中进行状态更改,然后在父组件中进行更改时,子组件将其状态重置为更改之前的状态。 我知道发生了什么,州政府没有被传递给家长

  • 问题: 有异步路由,从中获取参数并返回(组件)。问题是当我从一个到另一个(只是相同的路由,但不同。参数)我的路由器卸载并重新渲染组件。但它应该只传递新的道具,不要触及我的组件生命周期。怎么解决呢?我做错了什么? 代码: 路由器 组件将装入电影组件中 更新:好的,做了一些实验。 替换

  • 当按下{Link}并更改路由时,即使在react router dom的交换机组件之外,报头组件NavBar也会保持重新命名。 这里是文件: Main index.js文件: Home.js Contact.js 当前的项目非常简单:index.js文件包含Home和Contact组件,NavBar组件作为交换机外部的头。

  • 看看这支笔:https://codepen.io/segmentationfaulter/pen/XzgJyV 为了方便起见,我还在这里粘贴代码。打开上面的画笔后,您将看到一个滑块被渲染。向右滚动滑块,然后单击按钮,您将看到滑块以不同的数字重新渲染,但滑块的滚动位置不会重置。为什么滚动位置没有复位?谢谢

  • 问题内容: 我正在尝试将表示性组件与容器组件分开。我有一个和一个。容器负责触发redux操作,以根据当前用户获取适当的网站。 问题是在最初呈现容器组件之后,异步获取了当前用户。这意味着容器组件不知道它需要重新执行其函数中的代码,该代码将更新数据以发送到。我认为我需要在其props(user)之一更改时重新渲染容器组件。如何正确执行此操作? 问题答案: 您必须在方法中添加条件。 该示例用于比较对象。

  • 本文向大家介绍React-Router 4怎样在路由变化时重新渲染同一个组件?相关面试题,主要包含被问及React-Router 4怎样在路由变化时重新渲染同一个组件?时的应答技巧和注意事项,需要的朋友参考一下 在生命周期里面判断路由是否发生变化 参考:React 如何监听路由变化重新渲染组件