【问题标题】:Redirecting using React Router shows blank page使用 React Router 重定向显示空白页
【发布时间】:2019-10-23 07:27:42
【问题描述】:

我正在尝试使用 React 构建一个简单的示例项目,在该项目中,用户在单击按钮后被重定向到“联系人”页面。我试图通过设置状态属性的值来实现这一点。当我运行我拥有的代码时,它确实将浏览器地址栏 URL 更改为联系页面的 URL,但似乎并没有实际加载组件 - 我得到一个空白页面。如果我手动导航到该 URL (http://localhost:3000/contact),我可以看到内容。

这是我的 App.jsContact.js 文件 -

App.js

import React, { Component } from 'react';
import { BrowserRouter as Router, Switch, Route, Link, Redirect } from 'react-router-dom';
import Contact from './Contact';

class App extends Component {
    state = {
        redirect: false
    }

    setRedirect = () => {
        this.setState({
            redirect: true
        })
    }

    renderRedirect = () => {
        if (this.state.redirect) {
            return <Redirect to='/contact' />
        }
    }

    render() {
        return (
            <Router>
                <Switch>
                    <Route exact path='/contact' component={Contact} />
                </Switch>
                <div>
                    {this.renderRedirect()}
                    <button onClick={this.setRedirect}>Redirect</button>
                </div>
            </Router>
        )
    }
}

export default App;

Contact.js

import React, { Component } from 'react';

class Contact extends Component {
    render() {
        return (
            <div>
                <h2>Contact Me</h2>
                <input type="text"></input>
            </div>
        );
    }
}

export default Contact;

使用状态对我来说并不是真正的要求,所以其他(最好更简单的)重定向方法也会受到赞赏。

【问题讨论】:

    标签: javascript reactjs redirect react-router react-dom


    【解决方案1】:

    我来这里是为了一个类似的情况。可以使用withRouter (https://reactrouter.com/web/api/withRouter) 来处理。

    此示例已在 package.json 文件中的 "dependecies" 部分中使用 "react": "^16.13.1""react-router-dom": "^5.2.0""history": "^5.0.0" 进行了测试。

    在 App.js 中,我有 BrowserRouter(通常人们导入 BrowserRouter as Router,我更喜欢使用原始名称)与 Home 和 Contact。

    App.js

    import React, { Component } from "react";
    import {
        BrowserRouter,
        Switch,
        Route,
    } from "react-router-dom";
    import Home from "./pages/Home";
    import Contact from "./pages/Contact";
    class App extends Component
    {
        // stuff...
        render()
        {
            return (
                <BrowserRouter>
                    <Switch>
                        <Route path="/contact">
                            <Contact />
                        </Route>
                        <Route path="/">
                            <Home />
                        </Route>
                    </Switch>
                </BrowserRouter>
            );
        }
    }
    export default App;
    

    ASIDE 1Routepath="/contact" 放在 path="/" 之前,因为 Switch 渲染第一个匹配项,所以把 Home 放在最后。如果您有path="/something"path="/something/:id",则在之前放置更具体的路线(在本例中为/:id)。 (https://reactrouter.com/web/api/Switch)

    ASIDE 2我正在使用类组件,但我相信(我没有测试过)功能组件也可以工作。

    在 Home.js 和 Contact.js 中,我使用与 export 关键字关联的 withRouter。这使得 Home 和 Contact 组件通过props 接收BrowserRouterhistory 对象。使用方法push() 将“/contact”和“/”添加到历史堆栈。 (https://reactrouter.com/web/api/history)。

    Home.js

    import React from "react";
    import {
        withRouter
    } from "react-router-dom";
    
    export const Home = ( props ) =>
    {
        return (
            <div>
                Home!
                <button
                    onClick={ () => props.history.push( "/contact" ) }
                >
                    Get in Touch
                <button>
            </div>
        );
    }
    export default withRouter( Home );
    

    Contact.js

    import React from "react";
    import {
        withRouter
    } from "react-router-dom";
    
    export const Contact = ( props ) =>
    {
        return (
            <div>
                Contact!
                <button
                    onClick={ () => props.history.push( "/" ) }
                >
                    Go Home
                <button>
            </div>
        );
    }
    export default withRouter( Contact );
    

    特别是,我还在 BackButton 组件中使用 goBack() 向后导航:

    BackButton.js

    import React from "react";
    import {
        withRouter
    } from "react-router-dom";
    
    export const BackButton = ( props ) =>
    {
        return (
            <button
                onClick={ () => props.history.goBack() }
            >
                Go back
            <button>
        );
    }
    export default withRouter( BackButton );
    

    所以我可以将Contact 修改为:

    Contact.js(带有 BackButton)

    import React from "react";
    import BackButton from "../components/BackButton";
    
    export const Contact = ( props ) =>
    {
        return (
            <div>
                Contact!
                <BackButton />
            </div>
        );
    }
    export default Contact; // now I'm not using history in this file.
    // the navigation responsability is inside BackButton component.
    

    以上对我来说是最好的解决方案。其他可能的解决方案是:

    【讨论】:

      【解决方案2】:

      由于您的按钮只不过是一个链接,您可以将其替换为:

      <Link to="/contact">Redirect</Link>
      

      虽然有很多选择,例如您可以查看 BrowserRouter 的browserHistory

      import { browserHistory } from 'react-router'
      
      browserHistory.push("/contact")
      

      或者this.props.history.push("/contact")

      每种方法都有优点和缺点,你必须研究每种方法,看看你喜欢哪一种。

      【讨论】:

      • 最终我想构建一个登录表单,用户在成功登录后被重定向。感谢其他建议,我会研究一下。
      • 当我使用 this.props.history.push() 时,react 给我一个错误,提示“TypeError: Cannot read property 'push' of undefined”。当我尝试导入 browserHistory 时,它显示“尝试导入错误:'browserHistory' 未从 'react-router' 导出。”
      • import {withRouter} from react-router-dom 您可以通过 withRouter 高阶组件访问历史对象的属性和最近的路由匹配。 withRouter 将在渲染时将更新的匹配、位置和历史道具传递给包装的组件。
      猜你喜欢
      • 2022-07-21
      • 2020-01-30
      • 1970-01-01
      • 2022-03-23
      • 2022-01-22
      • 2021-09-23
      • 1970-01-01
      • 2017-06-21
      • 2017-04-22
      相关资源
      最近更新 更多