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 нашого компонента-подання.
Якщо виявили які-небудь недоліки, пишіть, виправлю. Дякую за увагу.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.