Изучаем Redux на примере создания мини-Redux

Nikolay Tolochny
devSchacht
Published in
3 min readApr 14, 2017

Перевод статьи Jakob Lind: Learn Redux by coding a Mini-Redux

Есть множество ресурсов по изучению Redux: официальная документация, примеры, руководства, блоги, шаблоны, Youtube видео, подкасты и так далее. Список можно продолжать. И хотя у нас есть так много замечательных ресурсов для изучения, появляющиеся новички по-прежнему впадают в замешательство. Из-за огромного количества материала, может быть сложно найти действительно стоящий.

Другая стратегия обучения — самостоятельное написание простой реализации Redux для развития глубокого понимания основополагающих принципов библиотеки. Для меня это был настоящий прорыв в моём процессе обучения. Теперь я чувствую, что знаю Redux, потому что я написал похожий код самостоятельно.

Не беспокойтесь, это не сложно. Ядро Redux удивительно простое. Вы увидите это в ходе чтения и написания кода по этой статье.

Прежде, чем мы начнём, нам необходимо общее представление о том, что же делает Redux.

Что делает Redux?

Суть Redux — иметь единственный источник состояния вашего приложения. Состояние хранится как обычный JavaScript объект в одном месте: в Redux Store (хранилище). Объект с состоянием доступен только для чтения. Если вы хотите изменить состояние, то вам необходимо эмитировать Action (действие), представляющий собой обычный JavaScript объект.

Ваше приложение может подписаться, чтобы получить уведомление об изменении хранилища. Когда Redux используется с React, компоненты React уведомляются об изменении состояния и могут перерисовываться на основе нового контента в хранилище.

Хранилищу необходим способ понять, как ему обновить свое состояние, когда он получает действие. Для этого оно использует обычную JavaScript функцию, которую Redux называет reducer (редьюсер). Редьюсер передается при создании хранилища.

Начнём программировать!

Подводя итог, мы должны иметь возможность делать с нашим хранилищем три вещи:

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

Мы также должны определить редьюсер и начальное состояние на момент запуска. Давайте с этого и начнём:

function createStore(reducer, initialState) {
var currentReducer = reducer;
var currentState = initialState;
}

1. Получение состояния

Итак, мы создали функцию, которая просто сохраняет начальное состояние и редьюсер как локальные переменные. Сейчас давайте реализуем возможность получать состояние нашего хранилища.

function createStore(reducer, initialState) {
var currentReducer = reducer;
var currentState = initialState;
return {
getState() {
return currentState;
}
};
}

Теперь мы можем получать объект состояния с помощью getState()! Это было несложно.

2. Передача действия

Следующий шаг — внедрить поддержку передачи действия.

function createStore(reducer, initialState) {
var currentReducer = reducer;
var currentState = initialState;
return {
getState() {
return currentState;
},
dispatch(action) {
currentState = currentReducer(currentState, action);
return action;
}
};
}

Функция dispatch передаёт текущее состояние и передает действие через редьюсер, который мы определили при инициализации. Затем она перезаписывает старое состояние новым состоянием.

3. Подписка на события

Теперь мы можем получать текущее состояние и обновлять его! Последний шаг — научиться слушать изменения:

function createStore(reducer, initialState) {
var currentReducer = reducer;
var currentState = initialState;
var listener = () => {};
return {
getState() {
return currentState;
},
dispatch(action) {
currentState = currentReducer(currentState, action);
listener(); // Заметьте, что мы добавили эту строку!
return action;
},
subscribe(newListener) {
listener = newListener;
}
};
}

Теперь мы можем вызвать subscribe c функцией обратного вызова в качестве параметра, которая будет вызываться всякий раз, когда происходит передача действия.

Мы закончили. Воспользуемся этим!

Вот и вся реализация мини-Redux! На самом деле, это урезанная версия настоящего кода Redux.

На официальном гитхабе Redux есть пример использования Redux. Мы можем скопировать и вставить этот пример, чтобы проверить нашу собственную реализацию Redux:

function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
let store = createStore(counter)store.subscribe(() =>
console.log(store.getState())
)
store.dispatch({ type: 'INCREMENT' })
store.dispatch({ type: 'INCREMENT' })
store.dispatch({ type: 'DECREMENT' })

Получить полный код для запуска на вашем компьютере вы можете здесь.

Заключение

Мы реализовали полностью рабочую версию Redux в восемнадцати строках кода! Довольно впечатляюще!

Код, который мы написали, само собой, не подходит для production. По сравнению с “реальным” Redux мы убрали обработку ошибок, не реализовали поддержку нескольких слушателей, не реализовали поддержку промежуточного ПО (middlewares) и так далее.

Теперь вы знаете основные принципы работы Redux и будете лучше подготовлены, продолжая ваше учебное путешествие!

В следующей статье мы будем реализовывать функцию connect, связывающую хранилище Redux c React компонентами.

Слушайте наш подкаст на SoundCloud, читайте на Medium, контрибьютьте на GitHub, общайтесь в группе Telegram, следите в Twitter и канале Telegram, рекомендуйте в VK и Facebook.

Статья на Github

--

--