Cách sử dụng Redirect trong react-router-dom mới của Reactjs


132

Tôi đang sử dụng mô-đun react-router phiên bản cuối cùng, có tên là react-router-dom, đã trở thành mặc định khi phát triển các ứng dụng web với React. Tôi muốn biết cách thực hiện chuyển hướng sau khi yêu cầu ĐĂNG. Tôi đã tạo mã này, nhưng sau khi yêu cầu, không có gì xảy ra. Tôi xem xét trên web, nhưng tất cả dữ liệu là về các phiên bản trước của bộ định tuyến phản ứng và không có với bản cập nhật cuối cùng.

Mã:

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;

1
Của bạn Redirecttrông giống như JSX, không phải JS.
elmeister

bạn có thể cung cấp cho bạn toàn bộ mã phần
KornholioBeavis

Có, tôi đang sử dụng JSX. Chà, có lẽ tôi cần phải làm rõ. Yêu cầu POST nằm bên trong một thành phần REACT tạo ra yêu cầu.
maoooricio

@KornholioBeavis, chắc chắn rồi, bây giờ bạn có thể thấy toàn bộ. Tôi làm cho máy chủ với expressjs, tôi không biết nếu bạn cần dữ liệu này
maoooricio

Bạn có thể xác thực rằng bạn đang nhận được phản hồi gọi lại từ axios.post không? Ngoài ra, tại sao bạn đang sử dụng hàm async mà không chờ đợi ở đâu?
KornholioBeavis

Câu trả lời:


197

Bạn phải sử dụng setStateđể thiết lập một thuộc tính sẽ hiển thị <Redirect>bên trong render()phương thức của bạn .

Ví dụ

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

Bạn cũng có thể xem ví dụ trong tài liệu chính thức: https://reacttraining.com/react-router/web/example/auth-workflow


Điều đó nói rằng, tôi sẽ đề nghị bạn đặt lệnh gọi API bên trong một dịch vụ hoặc thứ gì đó. Sau đó, bạn chỉ có thể sử dụng historyđối tượng để định tuyến theo chương trình. Đây là cách tích hợp với redux hoạt động.

Nhưng tôi đoán bạn có lý do của mình để làm theo cách này.


1
@sebastian sebald ý bạn là put the API call inside a service or somethinggì:?
andrea-f

1
Có một lệnh gọi API (không đồng bộ) như vậy bên trong thành phần của bạn sẽ khiến việc kiểm tra và sử dụng lại khó khăn hơn. Thông thường tốt hơn là tạo một dịch vụ và sau đó sử dụng nó (ví dụ) trong componentDidMount. Hoặc thậm chí tốt hơn, tạo HOC "bao bọc" API của bạn.
Sebastian Sebald

6
Chú ý rằng bạn phải bao gồm Redirect sử dụng nó trong bắt đầu của file: nhập khẩu {} Redirect từ 'phản ứng-router-dom'
Alex

3
Vâng, dưới mui xe Redirectđang gọi history.replace. Nếu bạn muốn truy cập vào historyobect, hãy sử dụng withRoutet/ Route.
Sebastian Sebald

1
react-router> = 5.1 hiện bao gồm các hook, vì vậy bạn có thể chỉ cầnconst history = useHistory(); history.push("/myRoute")
TheDarkIn1978

34

Đây là một ví dụ nhỏ về phản ứng đối với tiêu đề vì tất cả các ví dụ được đề cập đều phức tạp theo quan điểm của tôi cũng như chính thức.

Bạn nên biết cách chuyển đổi es2015 cũng như làm cho máy chủ của bạn có thể xử lý chuyển hướng. Đây là một đoạn trích cho express. Thông tin thêm liên quan đến điều này có thể được tìm thấy ở đây .

Đảm bảo đặt điều này bên dưới tất cả các tuyến đường khác.

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

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

Đây là tệp .jsx. Chú ý cách con đường dài nhất xuất hiện trước và tổng quát hơn. Đối với các tuyến đường chung nhất, hãy sử dụng thuộc tính chính xác.

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

1
điều này không hoạt động mọi lúc. nếu bạn có chuyển hướng từ home/hello> home/hello/1nhưng sau đó đi tới home/hellovà nhấn enter, nó sẽ không chuyển hướng lần đầu tiên. bất kỳ ý tưởng tại sao ??
The Walrus

Tôi khuyên bạn nên sử dụng "create-react-app" nếu có thể và làm theo tài liệu từ react-router. Với "create-react-app", mọi thứ đều hoạt động tốt đối với tôi. Tôi không thể điều chỉnh ứng dụng phản ứng của riêng mình với bộ định tuyến phản ứng mới.
Matthis Kohli


8

React Router v5 hiện cho phép bạn chuyển hướng đơn giản bằng cách sử dụng history.push () nhờ hook useHistory () :

import { useHistory } from "react-router"

function HomeButton() {
  let history = useHistory()

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

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

6

Hãy thử một cái gì đó như thế này.

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;

Nó hoạt động !, CẢM ƠN BẠN rất nhiều. Đây là một cách khác để làm điều này.
maoooricio

Bạn không nên thực hiện các yêu cầu HTTP trong các tệp thành phần của mình
Kermit_ice_tea 30/12/17

Bạn có thể chia sẻ những gì bên trong nhập SignUpForm từ '../../register/components/SignUpForm' ;? Tôi đang cố gắng học hỏi từ điều này. Mặc dù trong trường hợp của tôi, tôi đang sử dụng một hình thức Redux
phí chủ đề 'Topsy' Bello

3

Ngoài ra, bạn có thể sử dụng withRouter. Bạn có thể nhận được quyền truy cập vào các historythuộc tính của đối tượng và gần nhất <Route>'s matchqua các withRouterthành phần bậc cao. withRoutersẽ vượt qua được cập nhật match, locationhistoryđạo cụ để các thành phần quấn bất cứ khi nào nó ám.

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)

Hoặc chỉ:

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

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

1

bạn có thể viết một hoc cho mục đích này và viết một chuyển hướng cuộc gọi phương thức, đây là mã:

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;

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

Để điều hướng đến một trang khác (trang Giới thiệu trong trường hợp của tôi), tôi đã cài đặt prop-types. Sau đó, tôi nhập nó vào thành phần tương ứng this.context.router.history.push('/about')Và tôi đã sử dụng . Và nó được điều hướng.

Mã của tôi là,

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

0

Để điều hướng đến một thành phần khác, bạn có thể sử dụng this.props.history.push('/main');

import React, { Component, Fragment } from 'react'

class Example extends Component {

  redirect() {
    this.props.history.push('/main')
  }

  render() {
    return (
      <Fragment>
        {this.redirect()}
      </Fragment>
    );
   }
 }

 export default Example

1
Phản ứng ném một cảnh báo: Warning: Cannot update during an existing state transition (such as within làm). Render methods should be a pure function of props and state.
Robotron

0

Giải pháp đơn giản nhất để điều hướng đến một thành phần khác là (Ví dụ điều hướng đến thành phần thư bằng cách nhấp vào biểu tượng):

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

0

Ngoài ra, bạn có thể sử dụng kết xuất có điều kiện của 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>
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.