首页 > 解决方案 > 如果输入已提交,则重定向到不同的路由 - React Router

问题描述

我正在创建一个使用 OMDb 搜索电影的 React 应用程序。

我的应用程序分两个阶段工作:

以下是我的主要应用程序:

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

标签: reactjsreact-router

解决方案


鉴于您正在使用react-router-dom,您可以使用historypush()方法。这需要与使用Router 包装组件一起使用以公开必要的道具。这也需要对then()您的 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);

这是假设您为组件/路径定义了一个Route :Results

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)方法。

希望这会有所帮助!


推荐阅读