В этом посте мы напишем упрощенную версию магазина Redux, чтобы понять, как он работает.
Магазин
Store - это центральный репозиторий, в котором хранится состояние вашего приложения.
CreateStore
Сначала мы создаем функцию createStore()
, которая вернет хранилище, содержащее 4 части.
1. The store state 2. getState 3. subscribe (listening to changes on the state) 4. dispatch (updating the state)
Каждый раз, когда вы вызываете createStore()
, вы возвращаете объект, представляющий хранилище, которое содержит:
1. a way to getting state. 2. listening to changes on the state. 3. updating the state
Что касается состояния, оно не будет публично доступным, но вы можете взаимодействовать с ним, используя публичные методы, о которых мы говорили выше.
Итак, сначала нам нужен какой-то контейнер, который хранит внутреннее состояние, которое хранилище может изменить или получить к нему доступ с помощью 3 методов.
function createStore() { let state; }
getState
Теперь, когда это состояние локально доступно функции createStore()
, нам нужно создать способ взаимодействия с этим состоянием.
function createStore() { let state; function getState() { return state; } return { getState, }; }
Таким образом, когда пользователь создает хранилище и хочет получить доступ к состоянию, он может сделать это, вызвав getState ().
подписаться
Следующий шаг - заставить пользователя прислушиваться к изменениям состояния.
Мы делаем это, создавая переменную с именем `listeners`, которая изначально будет пустым массивом.
Каждый раз, когда вызывается `subscribe ()`, он получает функцию обратного вызова слушателя. И внутри мы вызываем `listeners`, который представляет собой массив, который мы создали, и нажимаем функцию обратного вызова слушателя, которая была получена при вызове подписки на этот массив.
function createStore() { let state; let listeners = []; function getState() { return state; } function subscribe(listener) { listeners.push(listener); } return { getState, subscribe, }; }
Итак, внутри `createStore ()` нам нужно отслеживать каждый раз, когда пользователь вызывает `store.subscribe ()`, и отслеживать эти переданные функции, чтобы при изменении состояния мы просматривали список функций и вызывали каждую из них. .
function createStore() { let state; let listeners = []; function getState() { return state; } function subscribe(listener) { listeners.push(listener); return function () { listeners = listeners.filter(function (listenerItem) { return listenerItem !== listener; }); }; } return { getState, subscribe, }; }
когда пользователь вызывает .subscribe, он возвращает функцию (функцию отмены подписки), и когда эта функция вызывается, мы хотим продолжить и удалить слушателя, который был передан для подписки из массива наших слушателей.
Другими словами, когда пользователь вызывает `.subscribe ()` и передает функцию слушателя, она будет помещена в массив слушателей, и они вернут функцию в результате вызова `.subscribe ()`.
Если они вызывают возвращаемую функцию, она фильтрует массив слушателей и удаляет функцию слушателя.
отправлять
Далее будет обновление состояния хранилища, поскольку мы хотим повысить предсказуемость, мы хотели бы указать тип событий, которые могут обновлять состояние, эти события называются «действиями».
«Действие» - это просто объект, который представляет событие, которое собирается изменить состояние нашего магазина. Действие должно иметь свойство `type`, чтобы указать тип выполняемого действия, кроме структуры на ваше усмотрение.
// action example { type: 'ADD_TODO', payload: { todo: { id: 0, name: 'Write a post about Redux' } } }
когда действие происходит внутри нашего приложения, мы хотим взять полезную нагрузку из входящего действия и добавить ее в состояние нашего приложения.
Это будет сделано внутри функции `reducer`, которая представляет собой чистую функцию, которая принимает текущее состояние и действие и в зависимости от типа действия будет указывать, как изменяется состояние.
Итак, теперь всякий раз, когда мы вызываем `dispatch ()`, он будет выполнять действие, а внутри него мы вызываем функцию редуктора, которая принимает текущее состояние и действие и собирается получить нам новое состояние, которое затем мы можем обновить внутри .
Всякий раз, когда мы обновляем состояние, нам нужно перебрать слушателей и вызвать их, чтобы они знали, что состояние было обновлено.
function dispatch(action) { state = reducer(state, action); listeners.forEach(function (listener) { return listener(); }); }
и вот весь магазин вместе
function createStore(reducer) { let state; let listeners = []; function getState() { return state; } function subscribe(listener) { listeners.push(listener); return function () { listeners = listeners.filter(function (listenerItem) { return listenerItem !== listener; }); }; } function dispatch(action) { state = reducer(state, action); listeners.forEach(function (listener) { return listener(); }); } return { getState, subscribe, dispatch, }; }
Пример
и ниже приведен пример использования методов хранилища
// reducer function - example function todos(state = [], action) { if (action.type === 'ADD_TODO') { return state.concat([action.payload]); } return state; } // create new store const store = createStore(todos); // to listen to the changes - something like a logger const unsubscribe = store.subscribe(() => { console.log('state: ', store.getState()); }); // to update the state store.dispatch({ type: 'ADD_TODO', payload: { todo: { id: 0, name: 'Write a post about Redux', }, }, });