Javascript 如何在 Reactjs 的新 react-router-dom 中使用 Redirect

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43230194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:45:39  来源:igfitidea点击:

How to use Redirect in the new react-router-dom of Reactjs

javascriptreactjsreact-router

提问by maoooricio

I am using the last version react-router module, named react-router-dom, that has become the default when developing web applications with React. I want to know how to make a redirection after a POST request. I have been making this code, but after the request, nothing happens. I review on the web, but all the data is about previous versions of the react router, and no with the last update.

我使用的是最新版本的 react-router 模块,名为 react-router-dom,它已成为使用 React 开发 Web 应用程序时的默认设置。我想知道如何在 POST 请求后进行重定向。我一直在制作这段代码,但是在请求之后,什么也没有发生。我在网上查看过,但所有数据都是关于 React 路由器的先前版本,并且没有与上次更新有关。

Code:

代码:

import React, { PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Redirect } from 'react-router'

import SignUpForm from '../../register/components/SignUpForm';
import styles from './PagesStyles.css';
import axios from 'axios';
import Footer from '../../shared/components/Footer';

class SignUpPage extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      errors: {},
      client: {
        userclient: '',
        clientname: '',
        clientbusinessname: '',
        password: '',
        confirmPassword: ''
      }
    };

    this.processForm = this.processForm.bind(this);
    this.changeClient = this.changeClient.bind(this);
  }

  changeClient(event) {
    const field = event.target.name;
    const client = this.state.client;
    client[field] = event.target.value;

    this.setState({
      client
    });
  }

  async processForm(event) {
    event.preventDefault();

    const userclient = this.state.client.userclient;
    const clientname = this.state.client.clientname;
    const clientbusinessname = this.state.client.clientbusinessname;
    const password = this.state.client.password;
    const confirmPassword = this.state.client.confirmPassword;
    const formData = { userclient, clientname, clientbusinessname, password, confirmPassword };

    axios.post('/signup', formData, { headers: {'Accept': 'application/json'} })
      .then((response) => {
        this.setState({
          errors: {}
        });

        <Redirect to="/"/> // Here, nothings happens
      }).catch((error) => {
        const errors = error.response.data.errors ? error.response.data.errors : {};
        errors.summary = error.response.data.message;

        this.setState({
          errors
        });
      });
  }

  render() {
    return (
      <div className={styles.section}>
        <div className={styles.container}>
          <img src={require('./images/lisa_principal_bg.png')} className={styles.fullImageBackground} />
          <SignUpForm 
            onSubmit={this.processForm}
            onChange={this.changeClient}
            errors={this.state.errors}
            client={this.state.client}
          />
          <Footer />
        </div>
      </div>
    );
  }
}

export default SignUpPage;

回答by Sebastian Sebald

You have to use setStateto set a property that will render the <Redirect>inside your render()method.

您必须使用setState设置一个属性来呈现<Redirect>您的render()方法内部。

E.g.

例如

class MyComponent extends React.Component {
  state = {
    redirect: false
  }

  handleSubmit () {
    axios.post(/**/)
      .then(() => this.setState({ redirect: true }));
  }

  render () {
    const { redirect } = this.state;

     if (redirect) {
       return <Redirect to='/somewhere'/>;
     }

     return <RenderYourForm/>;
}

You can also see an example in the official documentation: https://reacttraining.com/react-router/web/example/auth-workflow

你也可以在官方文档中看到一个例子:https: //reacttraining.com/react-router/web/example/auth-workflow



That said, I would suggest you to put the API call inside a service or something. Then you could just use the historyobject to route programatically. This is how the integration with reduxworks.

也就是说,我建议您将 API 调用放在服务或其他东西中。然后您可以使用该history对象以编程方式进行路由。这就是与 redux 集成的工作方式。

But I guess you have your reasons to do it this way.

但我想你有理由这样做。

回答by Matthis Kohli

Here a small example as response to the title as all mentioned examples are complicated in my opinion as well as the official one.

这里有一个小例子作为对标题的回应,因为在我看来,所有提到的例子和官方例子都很复杂。

You should know how to transpile es2015 as well as make your server able to handle the redirect. Here is a snippet for express. More info related to this can be found here.

您应该知道如何转译 es2015 以及如何让您的服务器能够处理重定向。这是express的一个片段。可以在此处找到与此相关的更多信息。

Make sure to put this below all other routes.

确保将其放在所有其他路线下方。

const app = express();
app.use(express.static('distApp'));

/**
 * Enable routing with React.
 */
app.get('*', (req, res) => {
  res.sendFile(path.resolve('distApp', 'index.html'));
});

This is the .jsx file. Notice how the longest path comes first and get's more general. For the most general routes use the exact attribute.

这是 .jsx 文件。请注意最长的路径是如何首先出现的,并且 get 更一般。对于最一般的路由,使用精确属性。

// Relative imports
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';

// Absolute imports
import YourReactComp from './YourReactComp.jsx';

const root = document.getElementById('root');

const MainPage= () => (
  <div>Main Page</div>
);

const EditPage= () => (
  <div>Edit Page</div>
);

const NoMatch = () => (
  <p>No Match</p>
);

const RoutedApp = () => (
  <BrowserRouter >
    <Switch>
      <Route path="/items/:id" component={EditPage} />
      <Route exact path="/items" component={MainPage} />          
      <Route path="/yourReactComp" component={YourReactComp} />
      <Route exact path="/" render={() => (<Redirect to="/items" />)} />          
      <Route path="*" component={NoMatch} />          
    </Switch>
  </BrowserRouter>
);

ReactDOM.render(<RoutedApp />, root); 

回答by Masum Billah

Simply call it inside any function you like.

只需在您喜欢的任何函数中调用它。

this.props.history.push('/main');

回答by KornholioBeavis

Try something like this.

尝试这样的事情。

import React, { PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Redirect } from 'react-router'

import SignUpForm from '../../register/components/SignUpForm';
import styles from './PagesStyles.css';
import axios from 'axios';
import Footer from '../../shared/components/Footer';

class SignUpPage extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      errors: {},
      callbackResponse: null,
      client: {
        userclient: '',
        clientname: '',
        clientbusinessname: '',
        password: '',
        confirmPassword: ''
      }
    };

    this.processForm = this.processForm.bind(this);
    this.changeClient = this.changeClient.bind(this);
  }

  changeClient(event) {
    const field = event.target.name;
    const client = this.state.client;
    client[field] = event.target.value;

    this.setState({
      client
    });
  }

  processForm(event) {
    event.preventDefault();

    const userclient = this.state.client.userclient;
    const clientname = this.state.client.clientname;
    const clientbusinessname = this.state.client.clientbusinessname;
    const password = this.state.client.password;
    const confirmPassword = this.state.client.confirmPassword;
    const formData = { userclient, clientname, clientbusinessname, password, confirmPassword };

    axios.post('/signup', formData, { headers: {'Accept': 'application/json'} })
      .then((response) => {
        this.setState({
          callbackResponse: {response.data},
        });
      }).catch((error) => {
        const errors = error.response.data.errors ? error.response.data.errors : {};
        errors.summary = error.response.data.message;

        this.setState({
          errors
        });
      });
  }

const renderMe = ()=>{
return(
this.state.callbackResponse
?  <SignUpForm 
            onSubmit={this.processForm}
            onChange={this.changeClient}
            errors={this.state.errors}
            client={this.state.client}
          />
: <Redirect to="/"/>
)}

  render() {
    return (
      <div className={styles.section}>
        <div className={styles.container}>
          <img src={require('./images/lisa_principal_bg.png')} className={styles.fullImageBackground} />
         {renderMe()}
          <Footer />
        </div>
      </div>
    );
  }
}

export default SignUpPage;

回答by Thanh-Quy Nguyen

React Router v5 now allows you to simply redirect using history.push() thanks to the useHistory() hook:

由于useHistory() 钩子,React Router v5 现在允许您使用 history.push() 简单地重定向:

import { useHistory } from "react-router"

function HomeButton() {
  let history = useHistory()

  function handleClick() {
    history.push("/home")
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  )
}

回答by ?mürcan Cengiz

Alternatively, you can use withRouter. You can get access to the historyobject's properties and the closest <Route>'s matchvia the withRouterhigher-order component. withRouterwill pass updated match, location, and historyprops to the wrapped component whenever it renders.

或者,您可以使用withRouter. 你可以访问history对象的属性和最近<Route>matchwithRouter高阶组件。每当它呈现时,withRouter都会将 updated matchlocationhistoryprops 传递给包装的组件。

import React from "react"
import PropTypes from "prop-types"
import { withRouter } from "react-router"

// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  }

  render() {
    const { match, location, history } = this.props

    return <div>You are now at {location.pathname}</div>
  }
}
// Create a new component that is "connected" (to borrow redux
// terminology) to the router.
const ShowTheLocationWithRouter = withRouter(ShowTheLocation)

Or just:

要不就:

import { withRouter } from 'react-router-dom'

const Button = withRouter(({ history }) => (
  <button
    type='button'
    onClick={() => { history.push('/new-location') }}
  >
    Click Me!
  </button>
))

回答by sojan

"react": "^16.3.2",
"react-dom": "^16.3.2",
"react-router-dom": "^4.2.2"

For navigate to another page (About page in my case), I installed prop-types. Then I import it in the corresponding component.And I used this.context.router.history.push('/about').And it gets navigated.

为了导航到另一个页面(在我的例子中是关于页面),我安装了prop-types. 然后我将它导入到相应的组件中。我使用了this.context.router.history.push('/about').And 它被导航。

My code is,

我的代码是,

import React, { Component } from 'react';
import '../assets/mystyle.css';
import { Redirect } from 'react-router';
import PropTypes from 'prop-types';

export default class Header extends Component {   
    viewAbout() {
       this.context.router.history.push('/about')
    }
    render() {
        return (
            <header className="App-header">
                <div className="myapp_menu">
                    <input type="button" value="Home" />
                    <input type="button" value="Services" />
                    <input type="button" value="Contact" />
                    <input type="button" value="About" onClick={() => { this.viewAbout() }} />
                </div>
            </header>
        )
    }
}
Header.contextTypes = {
    router: PropTypes.object
  };

回答by zia

you can write a hoc for this purpose and write a method call redirect, here is the code:

您可以为此目的编写一个 hoc 并编写一个方法调用重定向,这是代码:

import React, {useState} from 'react';
import {Redirect} from "react-router-dom";

const RedirectHoc = (WrappedComponent) => () => {
    const [routName, setRoutName] = useState("");
    const redirect = (to) => {
        setRoutName(to);
    };


    if (routName) {
        return <Redirect to={"/" + routName}/>
    }
    return (
        <>
            <WrappedComponent redirect={redirect}/>
        </>
    );
};

export default RedirectHoc;

回答by Hymankobec

The simplest solution to navigate to another component is( Example navigates to mails component by click on icon):

导航到另一个组件的最简单的解决方案是(示例通过单击图标导航到邮件组件):

<MailIcon 
  onClick={ () => { this.props.history.push('/mails') } }
/>

回答by Niyongabo

Alternatively, you can use React conditional rendering.

或者,您可以使用 React 条件渲染。

import { Redirect } from "react-router";
import React, { Component } from 'react';

class UserSignup extends Component {
  constructor(props) {
    super(props);
    this.state = {
      redirect: false
    }
  }
render() {
 <React.Fragment>
   { this.state.redirect && <Redirect to="/signin" /> }   // you will be redirected to signin route
}
</React.Fragment>
}