Диспетчеризация действий Redux при изменении местоположения с реакцией-маршрутизатором-домом - PullRequest
0 голосов
/ 18 мая 2018

Я использую React и Redux для поискового приложения.Используя react-router-dom, я маршрутизирую /search/:term? на компонент Search:

<Router>
  <Switch>
    <Route exact path="/search/:term?" component={Search} />
    <Redirect to="/search" />
  </Switch>

const Search = (props) => {
  const { term } = props.match.params;
  return (
    <div>
      <SearchForm term={term}/>
      <SearchResults />
    </div>
  )
};

Когда пользователь отправляет поиск в компоненте SearchForm,Я отправляю действие для отправки поискового запроса.Я также инициирую поиск в конструкторе, если дан термин, изначально:

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

    const term = props.term ? props.term : '';
    this.state = {
      term: term,
    }

    if (term) {
      this.props.submitSearch(term);
    }
  }

  handleSubmit = (e) => {
    e.preventDefault();
    if (this.state.term) {
      this.props.submitSearch(this.state.term);
    }
  }

  render = () => {
    <form
      onSubmit={this.handleSubmit.bind(this)}>
      ...
    </form>
  }
}

Я использую withRouter из react-router-dom, поэтому URL обновляется при отправке запроса.

Проблема возникает, когда пользователь переходит назад в своем браузере. URL переходит назад, реквизиты обновляются (т.е. props.match.params.term), но поиск не повторяется.Это связано с тем, что действие submitSearch отправляется только в SearchForm.constructor (поиск при начальной загрузке, если термин указан в URL) и SearchForm.handleSubmit.

. Как лучше всего прослушивать изменение состояния?term при изменении URL-адреса, а затем отправить поисковое действие?

Ответы [ 2 ]

0 голосов
/ 19 мая 2018

Я бы получил параметр маршрута в componentDidMount, поскольку вы нажимаете новый маршрут и, следовательно, перезагружаете представление.

Внутри вашей SearchForm это будет выглядеть следующим образом.

state = {
  term: '';
}

onChange = (term) => this.setState({ term })

onSubmit = () => this.props.history.push(`/search/${this.state.term}`);

И в вашем SearchResult:

componentDidMount() {
  this.props.fetchResults(this.props.term)
}

Хорошая вещь, которую нужно сделать, это сохранить компонент SearchResult сухим.Есть несколько способов добиться этого, вот один из них, использующий компоненты более высокого порядка или HOC :

export default FetchResultsHoc(Component) => {

  @connect(state => ({ results: state.searchResults }))
  class FetchResults extends React.Component {
    componentDidMount(){
      dispatch(fetchResults(this.props.match.params.term))
    }

    render(){
      <Component {...this.props} />
    }
  }

  return FetchResultsHoc;
}

, которые вы затем вызываете для компонента SearchResult, используя декоратор.

import { fetchResults } from './FetchResultsHoc';

@fetchResults
export default class SearchResult extends React.PureComponent { ... }
// You have now access to this.props.results inside your class
0 голосов
/ 18 мая 2018

Мое текущее решение - отправить submitSearch в методе жизненного цикла componentWillRecieveProps, если новые реквизиты не соответствуют текущим реквизитам:

componentWillReceiveProps(nextProps) {
  if (this.props.term !== nextProps.term) {
    this.setState({
      term: nextProps.term,
    });
    this.props.submitSearch(nextProps.term);
  }
}

Затем вместо отправки действия при отправке формыЯ нажимаю новое местоположение на history и componentWillReceiveProps выполняет диспетчеризацию:

handleSubmit = (e) => {
  e.preventDefault();
  if (this.state.term) {
    this.props.history.push('/search/'+this.state.term);
  }
}

Это решение кажется немного неправильным, но оно работает.(Казалось бы, другие согласны: Злые вещи, которые вы делаете с redux - рассылка обновлений методов жизненного цикла )

Я нарушаю принцип React или Redux, делая это?Могу ли я сделать лучше?

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