【问题标题】:react router v4 redirecting to another page outside of component反应路由器v4重定向到组件之外的另一个页面
【发布时间】:2018-01-22 18:15:39
【问题描述】:

我有一个我想要制作的基本短信应用程序,并且正在学习关于 react 和 meteor 的教程,但唯一的问题是该教程使用的是 react-router v3,我想习惯于 react-router v4。我将如何做出相当于做类似的事情:

browserHistory.replace("/chat");

我也在组件之外做,所以我不能这样做:

this.props.history.push("/chat");

每次有人进入页面时,我都会尝试运行一个函数,该函数会检查用户是否经过身份验证以及他们在哪个页面上。到目前为止,这是我的代码:

Main.js

import React from "react";
import ReactDOM from "react-dom";
import {Meteor} from "meteor/meteor";
import {Tracker} from "meteor/tracker";
import { BrowserRouter, Route, Switch, Redirect, withRouter} from 'react-router-dom'

import {Texts} from "./../imports/api/Text";
import App from "./../imports/ui/App";
import Name from "./../imports/ui/Name";
import NotFound from "./../imports/ui/NotFound";
import Signup from "./../imports/ui/Signup";
import Login from "./../imports/ui/Login";

Meteor.startup(() => {
    Tracker.autorun(() => {
        let texts = Texts.find().fetch();
        let signedIn = !!Meteor.userId();
        let onPrivatePage = ["/chat"];
        let onPublicPage = ["/signup", "/login"];
        const isUserAuthenticated = withRouter(({history}) => {
            if(signedIn && onPublicPage){
                console.log("Signed In")
            }
            if(!signedIn && onPrivatePage){
                console.log("Signed Out")
            }
        });
        const routes = (
            <BrowserRouter>
                <Switch>
                    <App path="/chat" texts={texts} render={isUserAuthenticated()}/>
                    <Signup path="/signup" render={isUserAuthenticated()}/>
                    <Login path="/login" render={isUserAuthenticated()}/>
                    <Route component={NotFound}/>
                </Switch>
            </BrowserRouter>
        );
        ReactDOM.render(routes, document.getElementById("app"));
    });
});

Signup.js

import React from "react"
import {withRouter} from "react-router-dom";
import {Accounts} from "meteor/accounts-base"
import {Link} from "react-router-dom";

class Signup extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            error: ""
        }
    }
    SignupUser(e){
        e.preventDefault();
        let username = this.refs.username.value;
        let password = this.refs.password.value;

        User = {
            username,
            password
        };

        Accounts.createUser(User, (err) => {
            if(err){
                this.setState({
                    error:err.reason
                })
            }else{
                console.log("success")
            }
        });
    }
    render(){
        return(
            <div>
                <form onSubmit={this.SignupUser.bind(this)}>
                    <h1>Register Here</h1>
                    {this.state.error}
                    <br />
                    <input type="username" ref="username" />
                    <input type="password" ref="password" />
                    <button>Signup</button>
                    <br />
                    <Link to="/login">I already have an account.</Link>
                </form>
            </div>

        )
    }
}
export default withRouter(Signup);

Login.js

import React from "react";
import {withRouter} from "react-router-dom";
import {Meteor} from "meteor/meteor";
import {Link} from "react-router-dom";

class Login extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            error:""
        }
    }
    loginUser(e){
        e.preventDefault()
        let username = this.refs.username.value.trim();
        let password = this.refs.password.value.trim();

        Meteor.loginWithPassword({username}, password, (err)=>{
            if(err){
                this.setState({
                    error: err.reason
                })
            }else{
                console.log("Logged in")
            }
        });
    }
    render(){
        return(
            <div>
                <form onSubmit={this.loginUser.bind(this)}>
                    <h1>Login</h1>
                    {this.state.error}
                    <br />
                    <input ref="username" type="text" placeholder="Username" />
                    <input ref="password" type="password" placeholder="Password" />
                    <button>Login</button>
                    <br />
                    <Link to="/signup">Need an account?</Link>
                </form>

            </div>
        )
    }
}

export default withRouter(Login);

【问题讨论】:

    标签: reactjs meteor react-router react-router-v4


    【解决方案1】:

    将您的 isUserAuthenticated 代码更改为以下内容:

    const isUserAuthenticated = withRouter(({history}) => {
        if(signedIn && onPublicPage){
            console.log("Signed In")
        }
        if(!signedIn && onPrivatePage){
            console.log("Signed Out")
        }
    });
    

    因此,您将能够在需要时执行 history.push('/some-route/') 。只是不要忘记在从react-router-dom 导入时添加withRouter,如下所示:

    import { BrowserRouter, Route, Switch, Redirect, withRouter } from 'react-router-dom'
    

    关于身份验证流程,请查看this auth example from React Router 4 docs。一定能帮到你!

    【讨论】:

    • 这段代码让我的应用崩溃了......
    • @StuartFong,感谢您指出这一点,实际上有一个错字!我有一个错误的)。你能再检查一下吗?如果您仍然遇到错误,请将其粘贴到此处,以便我进一步帮助您。
    • 关于您在 cmets 中的问题,({history}) 部分用于将 history 属性传递给 isUserAuthenticated 组件。就像写 (props) 但可以在组件内部直接写 history 而不是 props.history
    • 已更新!!当我这样做时,我收到一条错误消息“未捕获的类型错误:无法读取未定义的属性 'wrappedComponentRef'”
    • 你能把SignupLogin组件的代码贴出来吗?
    【解决方案2】:

    还有另一种方法可以做到这一点,它对 React Router v4 更友好,实际上也少了很多麻烦,并且涉及使用 Redirect 组件

    像这样导入组件:

    import { Link, Redirect } from 'react-router-dom';
    

    在你的渲染方法中做这样的事情:

    if (!Meteor.userId())
      return <Redirect to={"/login"} />
    

    或者,如果您想将其推送到历史记录中,请添加 push 属性

    if (!Meteor.userId())
      return <Redirect to={"/login"} push />
    

    【讨论】:

    • 抱歉回复晚了,我的应用程序已关闭,并且在重新启动时遇到了一些麻烦。当我使用 时,它什么都不做...如果我在同一个 if 语句中 console.log 它确实出现在控制台中但不重定向用户
    • 你是在你的渲染方法里做的吗?
    • 我在反应组件/类之外做这件事。我将它放在客户端上的 main.js 文件中,并检查用户是否在经过身份验证的页面上,如果他们在,那么我会将他们重定向到任何地方
    • 你在 React 之外做的任何事情都不会被 React 处理——你需要把它放在你的渲染方法中,然后你会发现它可以工作
    • 如果我的应用中有 10 个页面,我是否必须将其添加到每个页面中?或者我可以在 reactDOM 渲染的 routes.js 文件中执行此操作吗?
    猜你喜欢
    • 1970-01-01
    • 2017-11-05
    • 2022-01-20
    • 1970-01-01
    • 2017-08-13
    • 1970-01-01
    • 2018-11-23
    • 1970-01-01
    相关资源
    最近更新 更多