Прочитать начальное состояние магазина в редукторе Redux
начальное состояние в приложении Redux может быть установлено двумя способами:
- передайте его в качестве второго аргумента
createStore( "документы" по ссылке) - передайте его в качестве первого аргумента вашим (суб-)редукторам ( "документы" по ссылке)
Если вы передаете начальное состояние в свой магазин, как Вы читаете это состояние из магазина и делаете его первым аргументом в своих редукторах?
4 ответов:
TL; DR
без
combineReducers()или аналогичный ручной код,initialStateвсегда побеждаетstate = ...в редукторе, потому чтоstateперешел на редуктор иinitialStateи неundefined, поэтому синтаксис аргумента ES6 в этом случае не применяется.с
combineReducers()поведение более тонкое. Те редукторы, состояние которых указано вinitialStateполучите, чтоstate. Другие редукторы получатundefinedи упадет обратно вstate = ...аргумент по умолчанию они указывают.в общем,
initialStateвыигрывает над государством определенным редуктором. Это позволяет редукторам указывать исходные данные, которые имеют смысл в них как аргументы по умолчанию, но также позволяет загружать существующие данные (полностью или частично), когда вы увлажняющий магазин хранение ее в постоянном хранилище или сервер.первый рассмотрим случай, когда у вас есть один редуктор.
Скажите, что вы не используетеcombineReducers().затем ваш редуктор может выглядеть так:
function counter(state = 0, action) { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } }теперь предположим, что вы создаете магазин с ним.
import { createStore } from 'redux'; let store = createStore(counter); console.log(store.getState()); // 0начальное состояние равно нулю. Зачем? Потому что второй аргумент
createStoreбылundefined. Это и естьstateпрошло к вашему редуктору в первый раз. Когда Redux инициализирует его, он отправляет "фиктивное" действие для заполнения состояния. Так что вашcounterредуктор был вызван сstateравнаundefined. это именно тот случай, который "активирует" аргумент по умолчанию. таким образом,stateтеперь0по умолчаниюstateзначение (state = 0). Это состояние (0) будет возвращен.давайте рассмотрим другой сценарий:
import { createStore } from 'redux'; let store = createStore(counter, 42); console.log(store.getState()); // 42почему
42, а не0на этот раз? Потому чтоcreateStoreС42как второй аргумент. Этот аргумент становитсяstateпереданный к вашему редуктору вместе с фиктивным действием. в этот разstateне является неопределенным (это42!), поэтому синтаксис аргумента по умолчанию ES6 не имеет никакого эффекта. Thestateи42и42возвращается из редуктора.
Теперь рассмотрим случай, когда вы используете
combineReducers().
У вас есть два редуктора:function a(state = 'lol', action) { return state; } function b(state = 'wat', action) { return state; }редуктор, созданный
combineReducers({ a, b })выглядит так:// const combined = combineReducers({ a, b }) function combined(state = {}, action) { return { a: a(state.a, action), b: b(state.b, action) }; }если мы называем
createStoreбезinitialState, он собирается инициализироватьstateдо{}. Таким образом,state.aиstate.bбудетundefinedк тому времени он называетaиbредукторы. иaиbредукторы получитеundefinedкак ихstateАргументы, и если они указывают defaultstateзначения, которые будут возвращены. вот как комбинированный редуктор возвращает a{ a: 'lol', b: 'wat' }состояние объекта на первом вызов.import { createStore } from 'redux'; let store = createStore(combined); console.log(store.getState()); // { a: 'lol', b: 'wat' }давайте рассмотрим другой сценарий:
import { createStore } from 'redux'; let store = createStore(combined, { a: 'horse' }); console.log(store.getState()); // { a: 'horse', b: 'wat' }теперь я указал
initialStateв качестве аргументаcreateStore(). Состояние вернулось из комбинированного редуктора совместная начальное состояние, которое я указал дляaредуктор с'wat'аргумент по умолчанию указано, чтоbредуктор выбрал сам.вспомним, что делает комбинированный редуктор:
// const combined = combineReducers({ a, b }) function combined(state = {}, action) { return { a: a(state.a, action), b: b(state.b, action) }; }в этом случае
stateбыл указано, чтобы он не возвращался к{}. Это был объект с
в двух словах: это Redux тот, кто передает начальное состояние редукторам, вам ничего не нужно делать.
когда вы называете
createStore(reducer, [initialState])вы даете Redux знать, что такое начальное состояние, которое должно быть передано редуктору, когда приходит первое действие.второй вариант, который вы упомянули, применяется только в том случае, если вы не прошли начальное состояние при создании магазина. то есть
function todoApp(state = initialState, action)состояние будет инициализировано только в том случае, если его не было состояние передано Redux
Я надеюсь, что это ответ на ваш запрос (который я понял как инициализация редукторов при передаче intialState и возврате этого состояния)
вот как мы это делаем (предупреждение: скопировано из кода Typescript).
суть его в
if(!state)тест в функции mainReducer (factory)function getInitialState(): MainState { return { prop1: 'value1', prop1: 'value2', ... } } const reducer = combineReducers( { main: mainReducer( getInitialState() ), ... } ) const mainReducer = ( initialState: MainState ): Reducer => { return ( state: MainState, action: Action ): MainState => { if ( !state ) { return initialState } console.log( 'Main reducer action: ', action ) switch ( action.type ) { .... } } }
как Вы читаете это состояние из магазина и делаете его первым аргументом в своих редукторах?
combineReducers () делают работу за вас. Первый способ написать это не очень полезно:
const rootReducer = combineReducers({ todos, users })но другой, что эквивалентно более ясно:
function rootReducer(state, action) { todos: todos(state.todos, action), users: users(state.users, action) }
Comments