Reactjs의 새로운 react-router-dom에서 Redirect를 사용하는 방법


132

React로 웹 애플리케이션을 개발할 때 기본값이 된 react-router-dom이라는 마지막 버전의 react-router 모듈을 사용하고 있습니다. POST 요청 후 리디렉션하는 방법을 알고 싶습니다. 이 코드를 만들고 있지만 요청 후 아무 일도 일어나지 않습니다. 나는 웹에서 검토하지만 모든 데이터는 반응 라우터의 이전 버전에 관한 것이며 마지막 업데이트에는 없습니다.

암호:

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
귀하의 RedirectJSX 같은 외모, JS 없습니다.
elmeister

전체 구성 요소 코드를 제공 할 수 있습니까
KornholioBeavis

예, JSX를 사용하고 있습니다. 글쎄, 내가 분명히해야 할 것 같아. POST 요청은 요청을 만드는 REACT 구성 요소 내부에 있습니다.
maoooricio

@KornholioBeavis, 이제 완성 된 것을 볼 수 있습니다. 난 당신이 데이터를 필요로하는 경우 expressjs와 서버가, 나도 몰라 확인
maoooricio

axios.post에서 콜백 응답을 받고 있는지 확인할 수 있습니까? 또한 왜 어디서도 기다리지 않고 비동기 기능을 사용하고 있습니까?
KornholioBeavis

답변:


197

메서드 내부 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와의 통합이 작동하는 방식입니다.

그러나 나는 당신이 그렇게 할 이유가 있다고 생각합니다.


1
@sebastian sebald 당신은 무엇을 의미 put the API call inside a service or something합니까?
andrea-f

1
구성 요소 내부에 이러한 (비동기) API 호출이 있으면 테스트 및 재사용이 더 어려워집니다. 일반적으로 서비스를 만든 다음에서 사용하는 것이 좋습니다 (예 : componentDidMount. 또는 더 나은 방법은 API를 "래핑" 하는 HOC 를 만드는 것 입니다.
Sebastian Sebald

6
'이 라우터-DOM 반응'에서 가져 오기 {리디렉션}에주의는 포함해야 리디렉션은에서 파일의 시작 사용
알렉스

3
예, 후드 아래에서 Redirect를 호출 history.replace합니다. history개체에 액세스 하려면 withRoutet/를 사용하십시오 Route.
Sebastian Sebald

1
react-router> = 5.1은 이제 후크를 포함하므로 다음 작업 만 수행 할 수 있습니다.const history = useHistory(); history.push("/myRoute")
TheDarkIn1978

34

여기에 언급 된 모든 예로서 제목에 대한 응답으로서의 작은 예는 제 생각에는 물론 공식적인 예에서도 복잡합니다.

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 파일입니다. 가장 긴 경로가 먼저 오는 방법과 더 일반적입니다. 가장 일반적인 경로의 경우 정확한 속성을 사용합니다.

// 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
이것은 항상 작동하지 않습니다. home/hello> 에서 리디렉션이 home/hello/1있지만로 가서 home/helloEnter 키를 누르면 처음으로 리디렉션되지 않습니다. 왜 어떤 아이디어 ??
The Walrus

가능하면 "create-react-app"을 사용하고 react-router의 문서를 따르시기 바랍니다. "create-react-app"을 사용하면 모든 것이 잘 작동합니다. 내 반응 애플리케이션을 새로운 반응 라우터에 적용 할 수 없었습니다.
Matthis Kohli


8

React Router v5를 사용하면 useHistory () 후크 덕분에 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>
  )
}

6

이런 식으로 시도하십시오.

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;

작동합니다!, 정말 감사합니다. 이것은 이것을 수행하는 또 다른 방법입니다.
maoooricio

당신은 당신의 구성 요소 파일에 HTTP 요청을해서는 안
Kermit_ice_tea

'../../register/components/SignUpForm';에서 import SignUpForm 내부 내용을 공유 할 수 있습니까? 나는 이것으로부터 배우려고 노력하고있다. 제 경우에는 redux 양식을 사용하고 있습니다
Temi 'Topsy'Bello

3

또는 withRouter. 당신은에 액세스 얻을 수있는 history객체의 속성과 가장 가까운 <Route>'의 match비아 withRouter고차원 구성 요소를. 렌더링 할 때마다 withRouter업데이트 된 match, locationhistory소품을 래핑 된 구성 요소에 전달 합니다.

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)

아니면 그냥 :

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

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

1

이 목적을 위해 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;

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

다른 페이지 (제 경우에는 About 페이지)로 이동하기 위해 prop-types. 그런 다음 해당 구성 요소로 this.context.router.history.push('/about')가져오고.를 사용 하고 탐색됩니다.

내 코드는

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

다른 구성 요소로 이동하려면 다음을 사용할 수 있습니다. 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
React가 경고를 던졌습니다 : Warning: Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state.
Robotron 19

0

다른 구성 요소로 이동하는 가장 간단한 솔루션은 다음과 같습니다 (예 : 아이콘을 클릭하여 메일 구성 요소로 이동).

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

0

또는 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>
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.