перенаправить на другой маршрут, если вход был отправлен - React Router - PullRequest
0 голосов
/ 27 сентября 2018

Я создаю приложение React для поиска фильмов с использованием OMDb.

Мое приложение работает в два этапа:

  • Первоначально вы видите окно поиска
  • После отправки поля поиска с запросом фильма приложение должно перенаправитьна страницу результатов.

Ниже находится мое основное приложение:

class Muuvies extends Component {
    constructor() {
        super();

        this.state ={
            movies: [],
            error: "",
            searchedFor: "",
        };

        this.search = this.search.bind(this);
    }

    search({data}) {
        fetch(`http://www.omdbapi.com/?apikey=${OMDB_API_KEY}&s=${data}&type=movie`)
        .then(res => res.json())
        .then(res => {
            return res;
        }).then(json => this.setState({
            searchedFor: data,
            movies: propOr([], 'Search', json),
            error: json.Error
        })).catch(err => this.setState({
            error: 'Error Occurred: Try Again',
            movies: [],
            searchedFor: ''
        }));

        // if there wasn't an error, redirect to the Results page, passing what is returned from fetch().
    }

    render() {
    return (
        <Container>
            <Logo role="img" aria-label="search">?</Logo>
            <SearchWrapper>
                <Search search={this.search} />
                {
                    this.state.error
                    ? <Error><span role="img" aria-label="error" style={{marginRight: 2 + 'px'}}>⚠️</span>{this.state.error}</Error>
                    : null
                }
            </SearchWrapper>
        </Container>
    );
    }
}

Как мне изменить свое приложение так, чтобы, если пользователь отправил форму, а его нетошибка (например, this.state.error пусто после fetch()), затем он перенаправляет их на компонент Results?

Содержимое Search.js:

class Search extends Component {
  constructor(props) {
    super(props);

    this.state = {
      data: '',
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  handleChange(e) {
    this.setState({[e.target.name]: e.target.value});
  }

  handleSubmit(e) {
    e.preventDefault();
    this.props.search(this.state);
    this.setState({ data: '' });
  }

  render () {
    return (
      <StyledForm onSubmit={this.handleSubmit}>
        <StyledSearch id="data" type="text"
            name="data"
            placeholder="Search for Muuvies."
            value={path(['state', 'data'], this)}
            onChange={this.handleChange}
            autoComplete="off"
            autoFocus={true}
        />
      </StyledForm>
    )
  }
}

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Если вы используете react-router-dom, вы можете использовать history s push() метод.Это необходимо использовать с компонентом обтекания withRouter для предоставления необходимых реквизитовЭто также необходимо сделать с помощью then() do для асинхронной природы вашего вызова / поиска API:

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

class Muuvies extends Component {
    constructor() {
        super();

        this.state ={
            movies: [],
            error: "",
            searchedFor: "",
        };

        this.search = this.search.bind(this);
    }

    search({data}) {
        fetch(`http://www.omdbapi.com/?apikey=${OMDB_API_KEY}&s=${data}&type=movie`)
        .then(res => res.json())
        .then(res => {
            return res;
        }).then(json => {
          // you may not need this if your are redirecting
          this.setState({
              searchedFor: data,
              movies: propOr([], 'Search', json),
              error: json.Error
          }, () => {
            this.props.history.push("/results"); // or whatever string path
          });
        }).catch(err => this.setState({
            error: 'Error Occurred: Try Again',
            movies: [],
            searchedFor: ''
        }));

        // this would execute before API call/search is complete, need to do it in then()
    }

    render() {
    return (
        <Container>
            <Logo role="img" aria-label="search">?</Logo>
            <SearchWrapper>
                <Search search={this.search} />
                {
                    this.state.error
                    ? <Error><span role="img" aria-label="error" style={{marginRight: 2 + 'px'}}>⚠️</span>{this.state.error}</Error>
                    : null
                }
            </SearchWrapper>
        </Container>
    );
    }
} 

export default withRouter(Muuvies);

Это предполагает, что у вас есть Маршрут , определенный для вашего Results component / path:

import Results from './path/to/Results';

// ...

<Route path="/results" component={Results} />

Вы также можете использовать компонент Redirect в методе render(), возможно, на основе некоторых значений состояния:

import { Redirect } from 'react-router-dom';

// ...

render() {
   // check for error and maybe some other flag(s) such as a boolean property
   if (!this.state.error && this.state.submitted && this.state.movies.length > 0) {
     return <Redirect to={{ pathname: '/results', state: { movies: this.state.movies } }} />
   }

   // else render form or error maybe
}

ТоЕсли вы планируете перейти на уровне компонента к «/ results» или к какому-либо другому пути, вам, вероятно, не потребуется устанавливать состояние.При необходимости вы можете передать состояние в качестве второго аргумента методу history.push(path, state).

Надеюсь, это поможет!

0 голосов
/ 27 сентября 2018

Вы можете написать свой код здесь:

search({data}) {
    fetch(`http://www.omdbapi.com/?apikey=${OMDB_API_KEY}&s=${data}&type=movie`)
    .then(res => res.json())
    .then(res => {
        return res;
    }).then(json => {
        this.setState({
           searchedFor: data,
           movies: propOr([], 'Search', json),
           error: json.Error
        });
        //------
        //Write your code here, because if you got there, then there was no error at none of the "then" above
        //Or if a success response can contain an error field, you can check it with an if statement
        //------
    }).catch(err => this.setState({
        error: 'Error Occurred: Try Again',
        movies: [],
        searchedFor: ''
    }));

Код зависит от того, как вы структурируете свой проект и какие библиотеки вы используете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...