Как и где отправлять действия, когда реагирует роутер меняет реквизит - PullRequest
0 голосов
/ 06 июня 2018

Я могу что-то упустить здесь, изменение параметров реагирующего маршрутизатора с помощью Link приведет к изменению реквизита с новыми параметрами и вызовет цикл обновления.

Вы не можете отправить действиев цикле обновления, но это единственное место, где параметр доступен.Мне нужно получить новые данные при изменении параметра дня в моем компоненте без сохранения состояния.

Компонент имеет 2 ссылки, предыдущий и следующий день.Предыдущий день выглядит следующим образом:

<Link to={"/sessions/" + prefDay}>{prefDay}</Link>

[ОБНОВЛЕНИЕ]

Вот решение на данный момент:

Компонент Overview - это просто функция, принимающая реквизиты и возвращающая jsxниже приведен контейнер, который проверит, установлена ​​ли дата и, если нет, перенаправит.Если дата установлена, то он возвратит Overview.

Он также проверяет, изменился ли параметр дня маршрутизатора, если это так, то он установит dispatchFetch в значение true.

Это вызоветФункция рендеринга для асинхронной отправки действия getData.

Не уверен, что существует другой способ сделать это, я бы предпочел прослушивать события от маршрутизатора и отправлять события оттуда, но нет (рабочего) способаслушать роутер.

import { connect } from 'react-redux';
import React, { Component } from 'react';
import Overview from '../components/Overview';
import { getData } from '../actions';
import { selectOverview } from "../selectors";
import { Redirect } from "react-router-dom";


const defaultDate = "2018-01-02";
const mapStateToProps = (lastProps => (state, ownProps) => {
  var dispatchFetch = false;
  if (lastProps.match.params.day !== ownProps.match.params.day) {
    lastProps.match.params.day = ownProps.match.params.day;
    dispatchFetch = true;
  }
  return {
    ...selectOverview(state),
    routeDay: ownProps.match.params.day,
    dispatchFetch
  }
})({ match: { params: {} } });
const mapDispatchToProps = {
  getData
};
class RedirectWithDefault extends Component {
  render() {
    //I would try to listen to route change and then dispatch getData when
    //  routeDay changes but none of the methods worked
    //  https://github.com/ReactTraining/react-router/issues/3554
    //    onChange in FlexkidsApp.js never gets called and would probably 
    //      result in the same problem of dispatching an event in update cycle
    //    browserHistory does not exist in react-router-dom
    //    this.props.history.listen didn't do anything when trying it in the constructor
    //So how does one dispatch an event when props change in stateless components?
    //  can try to dispatch previous and next day instead of using Link component
    //  but that would not update the url in the location bar
    if (this.props.dispatchFetch) {
      Promise.resolve().then(() => this.props.getData(this.props.routeDay));
    }
    return (this.props.routeDay)//check if url has a date (mapStateToProps would set this)
      ? Overview(this.props)
      : <Redirect//no date, redirect
        to={{
          pathname: "/list/" + defaultDate
        }}
      />
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(RedirectWithDefault);

Ответы [ 4 ]

0 голосов
/ 07 июня 2018

В RedirectWithDefaults, который является контейнером компонента без состояния, я добавил componentDidMount (не метод цикла обновления):

const historyListener = (lastDay => (props,currentDay) => {
    if(lastDay !== currentDay){
        lastDay = currentDay;
        if(!isNaN(new Date(currentDay))){
            console.log("getting:",currentDay);
            props.getData(currentDay);
        }
    }
})(undefined);

class RedirectWithDefault extends Component {
    componentDidMount(history) {
        this.props.getData(this.props.routeDay || defaultDate);
        this.unListen = this.props.history.listen((location) => {
            historyListener(
                this.props,
                location.pathname.split('/').slice(-1)[0]
            );
        });
    }
    componentWillUnmount(){
        this.unListen();
    }

Удален код из функции рендеринга.Теперь, когда он монтируется, он отправляет действие для загрузки данных, а при изменении маршрута он отправляет его снова, но не в цикле обновления.

0 голосов
/ 06 июня 2018

Чтобы добавить параметр в маршрут, который вам нужен в маршрутизаторе, сделайте это

<Route 
     path="/sessions/:prefDay" 
                ....
/>  

Это означает, что теперь "/ session /" rout имеет параметр с именем "prefDay". Пример / session /: prefDay

и теперь в компоненте Link нужно добавить этот параметр

<Link to={"/sessions/" + prefDay}>{prefDay}</Link>

Вы можете получить это значение из URL, как это

this.props.match.params.prefDay
0 голосов
/ 06 июня 2018

Вы пробовали компонент WillReceiveProps?

componentWillReceiveProps(props){
   if(this.props.data != props.data && this.props.state.routeDay){
     this.props.getData(props.state.routeDay);
   }
}
0 голосов
/ 06 июня 2018

По сути, я ожидаю, что ваш маршрутизатор похож,

<Route path="/sessions/:prefDay" component={MyComponent}/>

Вам придется сделать это в getDerivedStateFromProps (),

static getDerivedStateFromProps(nextProps, prevState) {
    if (prevState.prefDay !== nextProps.match.params.prefDay) {

     return {
     prefDay: nextProps.match.params.prefDay,
     };
   }
   // Return null to indicate no change to state.
   return null;
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...