使用React Router进行重定向显示空白页。

5
我正在尝试构建一个简单的示例项目,当用户点击按钮时,使用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;

对我来说,使用状态并不是必需的,因此其他(最好更简单的)重定向方法也会受到欢迎。

2个回答

3

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

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

虽然有很多替代方案,但你可以尝试查看BrowserRouter的browserHistory

import { browserHistory } from 'react-router'

browserHistory.push("/contact")

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

每种方法都有其利弊,您需要研究每种方法并确定您更喜欢哪种。


最终我想要建立一个登陆表单,在用户成功登陆后重定向到其他页面。谢谢你提供的其他建议,我会仔细研究。 - Debadeep Sen
1
当我使用this.props.history.push()时, React会给我一个错误,说"TypeError: Cannot read property 'push' of undefined". 当我尝试导入 browserHistory 时,它会显示 "Attempted import error: 'browserHistory' is not exported from 'react-router'." - Debadeep Sen
import {withRouter} from react-router-dom使用withRouter高阶组件,您可以访问history对象的属性和最接近的Route的匹配。每当渲染时,withRouter将传递更新后的match,location和history props到包装的组件中。 - IAMSTR

1

我曾经遇到过类似的情况。可以使用 withRouter (https://reactrouter.com/web/api/withRouter) 来处理。

这个例子是在 "react": "^16.13.1""react-router-dom": "^5.2.0""history": "^5.0.0" 版本下测试的,它们都在 package.json 文件的 "dependecies" 部分中。

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

旁注1具有path="/contact"Route放在path="/"之前,因为Switch会渲染第一个匹配项,所以将Home放在最后。如果你有path="/something"path="/something/:id",请将更具体的路由(在这种情况下是带有/:id的路由)放在前面。(https://reactrouter.com/web/api/Switch

旁注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(带有返回按钮)

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.

以上是我最好的解决方案。其他可能的解决方案包括:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接