Контейнер предсказуемого состояния для приложений JavaScript
Что такое Редукс?
- Redux — это контейнер предсказуемого состояния, разработанный, чтобы помочь вам писать приложения JavaScript, которые одинаково ведут себя в клиентских, серверных и собственных средах и которые легко тестировать.
- Redux был создан Дэном Абрамовым примерно в июне 2015 года. Он был вдохновлен Flux от Facebook и языком функционального программирования Elm. Redux очень быстро стал популярным из-за его простоты, небольшого размера (всего 2 КБ) и отличной документации.
Принципы редукса
Предсказуемость Redux определяется тремя наиболее важными принципами, указанными ниже:
- Единый источник достоверной информации.Состояние всего вашего приложения хранится в дереве объектов в одном хранилище. Поскольку все состояние приложения хранится в одном дереве, это упрощает отладку и ускоряет разработку.
- Состояние доступно только для чтения.Единственный способ изменить состояние — это выполнить действие, объект, описывающий, что произошло. Это означает, что никто не может напрямую изменить состояние вашего приложения.
- Изменения вносятся с помощью чистых функций.Чтобы указать, как дерево состояний преобразуется действиями, вы пишете чистые редукторы. Редуктор — это центральное место, где происходит изменение состояния. Редьюсер — это функция, которая принимает текущее состояние и действие для выполнения. Функция должна возвращать недавно обновленное состояние, а не измененную версию существующего состояния.
Строительные части Redux
Redux состоит из трех частей: действия, хранилище и редюсеры.
Действия в Redux
Короче говоря, действия — это события. Это единственный способ отправить данные из вашего приложения в магазин Redux. Данные могут быть получены из взаимодействия с пользователем, внутренних событий, таких как вызовы API, или даже отправки форм.
- Действия — это простые объекты JavaScript, и они должны иметь свойство type (обычно постоянное), указывающее тип выполняемого действия. Они также должны иметь полезную нагрузку, содержащую информацию, над которой должно работать действие.
{ type: "LOGIN", payload: { username: "Ayush", password: "12345" } }
- Действия создаются с помощью создателей действий. Это звучит очевидно, я знаю. Это просто функции, которые возвращают действия.
const setLoginStatus = (name, password) => { return { type: "LOGIN", payload: { username: "Ayush", password: "12345" } } }
- Действия отправляются методом
store.dispatch()
.
store.dispatch(setLoginStatus(name, password));
Редукторы в Redux
Редьюсеры — это чистая функция в Redux. Чистые функции предсказуемы. Редьюсеры — единственный способ изменить состояние в Redux.
- Это единственное место, где вы можете писать логику и расчеты. Функция редуктора примет предыдущее состояние приложения и отправляемого действия, рассчитает следующее состояние и вернет новый объект.
- Следующие несколько вещей никогда не должны выполняться внутри редуктора: мутация аргументов функций, вызовы API и логика маршрутизации, а также вызов нечистой функции, например. Math.random()
- Он основан на функции
reduce
в JavaScript, где одно значение вычисляется из нескольких значений после выполнения функции обратного вызова.
Redux reducer signature(previousState, action) => nextState
Array.prototype.reduce signature(accumulator, value) => (accumulator + value)
Example: consthandleAuth
= (state = initialState, action) => { switch (action.type) { // This reducer handles any action with type "LOGIN" case "LOGIN": return state.map(user => { if (user.username !== action.payload.username) { return user; } if (user.password == action.payload.password) { return { ...user, login_status: "LOGGED IN" } } }); default: return state; } };
- Как чистые функции, они не изменяют данные в переданном им объекте и не выполняют никаких побочных эффектов в приложении. Имея один и тот же объект, они всегда должны давать один и тот же результат.
- Для более сложных приложений возможно использование утилиты
combineReducers()
, предоставляемой Redux (действительно, рекомендуется). Он объединяет все редукторы в приложении в один индексный редуктор. Каждый редьюсер отвечает за свою часть состояния приложения, и параметр состояния у каждого редьюсера разный. УтилитаcombineReducers()
значительно упрощает обслуживание файловой структуры.
const rootReducer = combineReducers({
handleAuth: handleAuth,
editProfile: editProfile,
changePassword: changePassword
});
Магазин в Редукс
Магазин — это неизменное дерево объектов в Redux. В хранилище хранится состояние приложения. Настоятельно рекомендуется хранить только одно хранилище в любом приложении Redux. Магазин имеет следующие обязанности:
- Разрешает доступ к состоянию через
getState()
; - Позволяет обновлять состояние через
dispatch(action)
; - Регистрирует слушателей через
subscribe(listener)
; - Обрабатывает отмену регистрации слушателей с помощью функции, возвращаемой
subscribe(listener)
. - createStore-функция может иметь три аргумента. Редьюсер — это функция, которая возвращает следующее состояние приложения. PreloadedState — это необязательный аргумент, который является начальным состоянием вашего приложения. Энхансер также является необязательным аргументом. Это поможет вам расширить магазин сторонними возможностями.
Syntax - createStore(reducer, [preloadedState], [enhancer])Example: import { createStore } from ‘redux’;
import rootReducer from './reducers/index'; const store = createStore(rootReducer
);
- Действия, выполняемые над состоянием, всегда возвращают новое состояние через редьюсеры. Таким образом, состояние очень легкое и предсказуемое.
store.dispatch(
setLoginStatus(‘alex’
,‘123456’
));
Редукс — ПО промежуточного слоя
- Сам Redux является синхронным, так как же асинхронные операции, такие как сетевые запросы, работают с Redux? Здесь пригодятся промежуточные программы.
- Как обсуждалось ранее, редукторы — это место, где записывается вся логика выполнения. Редьюсер не имеет ничего общего с тем, кто его выполняет, сколько времени это занимает или регистрирует состояние приложения до и после отправки действия. В этом случае функция промежуточного программного обеспечения Redux предоставляет среду для взаимодействия с отправленным действием до того, как оно достигнет редюсера.
- Обычно ПО промежуточного слоя используется для обработки асинхронных действий в вашем приложении. Redux предоставляет API под названием applyMiddleware, который позволяет нам использовать собственное промежуточное ПО, а также промежуточное ПО Redux, такое как redux-thunk и redux-saga. И это можно применить для хранения следующим образом:
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers/index'; const store = createStore(rootReducer, applyMiddleware(thunk));
- Промежуточное программное обеспечение позволит вам написать диспетчер действий, который возвращает функцию вместо объекта действия.
function getUser() { return function() { return axios.get('/get_user_details'); }; }
- Технически промежуточное программное обеспечение — это функции, которые вызывают следующий метод, полученный в аргументе, после обработки текущего действия. Они вызываются после каждой отправки. Вот как выглядит простое промежуточное ПО:
Syntax - ({ getState, dispatch }) => next => action function simpleMiddleware({ getState, dispatch }) { return function(next){ return function(action){ // processing const nextAction = next(action); // read the next state const state = getState(); // return the next action or you can dispatch any other action return nextAction; } } } const store = createStore(rootReducer , initialState=[ ] , applyMiddleware(simpleMiddleware));
Зачем использовать Redux?
- Предсказуемость результата.Всегда есть один источник правды, хранилище, и нет путаницы в том, как синхронизировать текущее состояние с действиями и другими частями приложения.
- Сопровождаемость.Предсказуемый результат и строгая структура облегчают поддержку кода. Это также поможет вам отделить бизнес-логику от дерева компонентов. Для крупномасштабных приложений очень важно, чтобы ваше приложение было более предсказуемым и ремонтопригодным.
- Организация.Redux строже относится к организации кода, что делает код более согласованным и с ним проще работать команде.
- Рендеринг на сервере.Это очень полезно, особенно для первоначального рендеринга, что позволяет улучшить взаимодействие с пользователем или оптимизировать поисковую систему. Просто передайте хранилище, созданное на сервере, на сторону клиента.
- Инструменты для разработчиков. Разработчики могут отслеживать все, что происходит в приложении, в режиме реального времени, от действий до изменений состояния. Это дает вам возможность редактировать код в реальном времени в сочетании с отладчиком, путешествующим во времени.
- Сообщество и экосистема.Это огромный плюс, когда вы изучаете или используете какую-либо библиотеку или фреймворк. Наличие сообщества позади Redux делает его еще более привлекательным в использовании.
- Простота тестирования.Первое правило написания тестируемого кода — писать небольшие функции, которые делают только одну вещь и являются независимыми. Код Redux в основном состоит из таких функций: маленьких, чистых и изолированных.
- Преимущества в производительности. Можно предположить, что сохранение глобального состояния приложения приведет к некоторому снижению производительности. В значительной степени это не так. React Redux реализует множество внутренних оптимизаций производительности, поэтому ваш собственный подключенный компонент выполняет повторную визуализацию только тогда, когда это действительно необходимо.
Redux DevИнструменты
- Последним полезным шагом в работе с Redux является установка и запуск собственных инструментов разработки Redux. Если вы используете Chrome, вы можете включить Redux DevTools, перейдя по ссылке ниже:
- Но есть еще один шаг, чтобы заставить его работать. В нашем методе
createStore
нам нужно передать в качестве аргумента после нашего редуктора следующее:window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()()
. С этим дополнениемstore.js
должно выглядеть так:
import { createStore } from 'redux'; import reducer from './reducers'; const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()); export default store;
- Теперь мы сможем получить доступ к Redux DevTools из панели Chrome DevTools (нажав CTRL/CMD + Shift + I) и выбрав Redux.
Вывод
Мы узнали об основах, компонентах сборки и использовании Redux. А для реализации Redux с нуля вы можете прочитать эту статью —
Надеюсь, что после этого вы почувствуете себя более комфортно с Redux.
Спасибо за прочтение :)
Дополнительные материалы на codecrunch.org