Redux является предсказуемым контейнером состояния для JavaScript приложений. Это позволяет вам создавать приложения, которые ведут себя одинаково в различных окружениях (клиент, сервер и нативные приложения), а также просто тестируются.
Redux решает проблему управления состоянием в приложении, предлагая хранить данные в глобальном State, и централизованно изменяя его.
- Компоненты формируют события (actions).
- Reducer — модуль логики, который обрабатывает
listeners и изменяет state. - State общий для всех компонентов.
- Reducer + State = Store.
- Компоненты обновляются при изменении state.
Установка
npm install redux react-redux // устанавливаем 2 библиотеки
Reducer
Это функция, которая принимает на вход команды и изменяет state. Если тип action неизвестен, возвращаем state. Пример реализации на JavaScript:
const reducer = (state = 0, action) => {
switch (action.type) {
case 'inc':
return state + 1;
break;
default: return state;
}
}
let state = reducer(undefined, {}); // инициализация
console.log(state) // 0
state = reducer(state, {type: 'inc'});
console.log(state) // 1
Redux-store
Store содержит всё дерево состояний приложения. Единственный способ изменить состояние внутри него — отправить на него action.
createStore(reducer)
Store — это не класс. Это просто объект с несколькими методами. Чтобы создать его, передайте свою функцию в createStore
const store = createStore(reducer);
getState()
Возвращает текущее дерево состояний вашего приложения. Он равен последнему значению, которое возвращает store’s reducer.
dispatch(action)
store.dispatch(action) — отправляет команду, и это единственный способ вызвать изменение состояния store.
Store’s reducer будет вызываться с текущим getState() результатом и заданным action, синхронно. Его возвращаемое значение будет считаться следующим состоянием. Он будет возвращен с новым getState(), и слушатели изменений будут немедленно уведомлены.
subscribe(listener)
Добавляет слушателя изменений. Вызывается каждый раз, когда store может быть изменён.
Как это работает вместе
import {createStore} from 'redux';
const reducer = (state=0, action) => {
switch (action.type) {
case 'inc':
return state + 1;
case 'dec':
return state -1;
default: return state;
}
}
const store = createStore(reducer);
const update = () => {
console.log(store.getState()); // при каждом обращение к store будет выводить его значение
}
store.subscribe(update); // Подписываемся на вызов store
store.dispatch({type: 'inc'}); // 1
store.dispatch({type: 'inc'}); // 2
store.dispatch({type: 'abrahabra'}); // 2 - такой команды нет, поэтому state не изменился
store.dispatch({type: 'dec'}); // 1
Actions Creators
В store может передаваться много данных, поэтому бывает удобно сделать функции создатели действий.
const login = (name, role) => {
return {type: login, name: name, role: role}
}
store.dispatch(login('Sergey', 'user');
bindActionCreators()
bindActionCreators(actionCreators, dispatch)
Превращает объект, значения которого являются actions creators, в объект с теми же ключами, но с каждым action creator, заключенным в dispatch-вызов, чтобы их можно было вызывать напрямую.
Единственный вариант использования для bindActionCreators- это когда вы хотите передать actions creators в компонент, который не знает о Redux, и вы не хотите передавать dispatch или хранить Redux в нем.
Структура проекта
Если у много actions creators, разумно вынести их в отдельный файл, или папку. То же касается Reducer’а.
React-Redux
Provider
import {Provider} from 'react-redux';
// ...
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'));
connect()
connect — это компонент высшего порядка (HOC), который создаёт новые компоненты.
Источники:
- Документация по Redux на русском.
- Документация по Store-Redux.
- bindActionCreators().
- react-redux.
- Юрий Бура. Курс «React + Redux — Профессиональная Разработка» —
а возможно ли сделать диспатч по состоянию? у состояния имеется параметр. работает функция, которая от него зависит. и пока он не изменится она не продолжит выполняться. или выполнится при изменении этого параметра стейта.