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

IT技术 javascript reactjs react-router
2021-01-12 12:13:57

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

代码:

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;
6个回答

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

例如

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/>;
}

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


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

但我想你有理由这样做。

在您的组件中使用这样的(异步)API 调用会使测试和重用变得更加困难。通常最好创建一个服务,然后在componentDidMount. 或者更好的是,创建一个“包装”您的 APIHOC
2021-03-25 12:13:57
react-router >=5.1 现在包括钩子,所以你可以 const history = useHistory(); history.push("/myRoute")
2021-04-03 12:13:57
请注意,您必须包含 Redirect 才能在文件开头使用它: import { Redirect } from 'react-router-dom'
2021-04-05 12:13:57
@sebastian sebald 你是什么意思:put the API call inside a service or something
2021-04-09 12:13:57
是的,引擎盖下Redirect正在调用history.replace如果要访问history对象,请使用withRoutet/ Route
2021-04-10 12:13:57

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

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

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

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

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

这是 .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); 
我建议您尽可能使用“create-react-app”并遵循 react-router 的文档。使用“create-react-app”对我来说一切正常。我无法使我自己的 React 应用程序适应新的 react-router。
2021-03-12 12:13:57
这并不总是有效。如果您从home/hello>重定向,home/hello/1然后转到home/hello并按 Enter 键,则不会第一次重定向。任何想法为什么?
2021-03-13 12:13:57

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

import { useHistory } from "react-router-dom"

function HomeButton() {
  let history = useHistory()

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

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  )
}
现在,我们从react-router-dom.
2021-03-24 12:13:57

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

this.props.history.push('/main');
外部组件呢?
2021-03-15 12:13:57
在此处查看这些问题: github.com/ReactTraining/react-router/issues/... @Nux
2021-03-31 12:13:57

尝试这样的事情。

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;
您不应该在组件文件中发出 HTTP 请求
2021-03-17 12:13:57
你能分享一下 import SignUpForm from '../../register/components/SignUpForm' 里面的内容吗?我正在尝试从中学习。虽然就我而言,我使用的是 redux 形式
2021-03-28 12:13:57