React Redux. Получение доступа к state из функции mapDispatchToProps()

от автора

Всем привет! Сегодня рассмотрим решение, довольно-таки популярной проблемы — получение доступа к state из функции mapDispatchToProps() react-redux приложения.

Имеется типовой компонент-контейнер (про идеологию компонентов react-redux можно почитать здесь), который генерирую с помощью функции connect(). Код представлен ниже (публикую кусок кода, относящийся к данной теме):

const mapStateToProps = (state) => {     return state.play; };  const mapDispatchToProps = (dispatch) => {     return {         togglePlay: () => {             dispatch(togglePlay());         }     } };  const ButtonPlayComponentContainer = connect(     mapStateToProps,     mapDispatchToProps )(ButtonPlayComponentView);

Тут все просто, определяем функции mapStateToProps() для чтения состояния и mapDispatchToProps() для передачи события. Далее генерируем компонент путем передачи созданных функций в connect().

В добавок публикую код метода render() компонента-представления, для более ясной картины:

render() {     return(         <div className="button-play" onClick={this.props.togglePlay}>             <i className={ this.props.play == false ? "fa fa-play" : "fa fa-pause" }></i>         </div>     ); };

Обычная ситуация, при клике на кнопку, меняется state и в зависимости от состояния, меняется класс у элемента.

Но теперь появляется задача, при изменении состояния, возвращать ту или иную функцию. Вроде бы не сложно, проблема решается одним if, но есть одно но. У нас нет доступа к state в методе mapDispatchToProps(). С лету, на ум приходит сразу один вариант — сделать запрос к хранилищу с помощью метода getState() и получить текущее состояние. Но такой вариант смутил меня своей бестолковостью. Ибо пропадает весь смысл в функции mapStateToProps, которая и так отвечает за состояние.

Просмотрев документацию по методу connect() (на этот раз внимательно), обнаружил параметр mergeProps:

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]);

Выдержка из документации по данному параметру:

You may specify this function to select a slice of the state based on props, or to bind action creators to a particular variable from props.

Если дословно переводить, но получается, что данная функция дает возможность получить текущее состояние, либо передавать события путем привязки нашего экшена к переменной из props (то что делает mapDispatchToProps()). Отлично, убиваем двух зайцев одним выстрелом.

Немного погуглив, по теме реализации метода mergeProps, наткнулся на вопрос на github.

В итоге, получаем:

const mapStateToProps = (state) => {     return state.play; };  const mergeProps = (stateProps, dispatchProps) => {     const { play } = stateProps;     const { dispatch } = dispatchProps;      const toggle = () => {         dispatch(togglePlay());         if (play != true) {             this.playAction();         } else {             this.stopAction();         }     };      return {         play: play,         togglePlay: () => {             toggle();         }     }; };  const ButtonPlayComponentContainer = connect(     mapStateToProps,     null,     mergeProps )(ButtonPlayComponentView);

Тут тоже все просто, в mergeProps прилетают stateProps, который содержит текущее состояние и dispatchProps, который дает возможность отправить событие. Далее по коду делаем проверку на состояние, результатом которой будет нужная функция и возвращаем объект с текущим state и событием, который благополучно попадет в props нашего компонента-представления.

Если обнаружили какие-нибудь недочеты, пишите, поправлю. Спасибо за внимание.

ссылка на оригинал статьи https://habrahabr.ru/post/314582/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *