如何在Redux中设置初始状态

65
4个回答

90

它需要作为createStore的第二个参数:

const rootReducer = combineReducers({
  todos: todos,
  visibilityFilter: visibilityFilter
});

const initialState = { 
  todos: [{id:123, text:'hello', completed: false}] 
};

const store = createStore(
  rootReducer, 
  initialState
);

1
如果我在reducer中没有指定默认状态值并且提供了初始状态给createStore,那么状态将不会被正确设置。 - lazy.lizard

40

您可以在reducer中设置初始状态。

const initialTodos = [{id:123, text:'hello', completed: false}]

// this is the ES2015 syntax for setting a default value for state in the function parameters
function todoReducer(state = initialTodos, action) {
  switch(action.type) {
    ... 
  }
  return state
}


const todoApp = combineReducers({
  // todos now defaults to the array of todos that you wanted and will be updated when you pass a new set of todos to the todoReducer
  todos: todoReducer,
  visibilityFilter
})

3
@ctrlplusb和这个有什么不同呢? - Arthur Attout
5
jmancherje的做法实际上是Redux推荐的:https://redux.js.org/recipes/structuring-reducers/initializing-state#single-simple-reducer - boaz_shuster
2
是的,你应该在reducers上明确定义默认状态,我只是觉得OP正在寻找与完整存储重建相关的解决方案(例如SSR/localstorage)。 - ctrlplusb

3
迄今为止已经有很好的答案了,但让我来点缀一下;也许给你一个深入的分析,这样你就不只是复制那些可用但不知道为什么程序可以工作的StackOverflow代码。
有两种主要的方法可以实现这个目标,即: 1. 使用createStore方法。它接受一个可选的第二个参数(预加载状态值)。
const store = createStore(counter) // createStore without preloadedState
const initialState = {} // or in your case:
const initialState = {
                         initialTodos = [{id:123, text:'hello', completed: false}]
                     }
const store = createStore(counter, initialState) // create store with preloadedState

如果您调用createStore时没有提供preloadedState,它将初始化state为 {}。 因此,reducers将收到undefined作为它们的状态值。 这就引出了第二种方法。

  1. 您可以在reducers中设置initialState。通过查看传入的state参数(如果没有使用initialState调用createStore,则该参数将为undefined)并返回想要用作默认值的值来设置initialState
const initialState = {} // a common pattern but in your case:
const initialState = {
                         initialTodos = [{id:123, text:'hello', completed: false}]
                     }
function todoReducer(state = initialState, action) {
  switch (action.type) {
    case // your type:
      return ...
    default:
      return state
  }
}

方法2的缺点在于当数据非常庞大时,比如一个巨大的待办事项列表需要作为“全局应用程序”传递给initialState。方法2将带来很多重复性工作,因为您必须在所有的Reducer中都执行相同的操作。这是主要的缺点。但是当你只想设置initialState as {}时,它是一种常见的模式。

这里有一篇4分钟阅读的文章,以便更好地理解:https://dev.to/lawrence_eagles/how-to-properly-set-initial-state-in-redux-78m


0
根据@ctrlplusb的回答,这个方法可行的原因是因为:
const rootReducer = combineReducers({
  todos: todos,
  visibilityFilter: visibilityFilter
});

第一个todos是一个键,它将第二个todos设置为reducer的返回值。Reducers总是在存储创建时运行一次。这将初始化您的全局存储。

当存储被创建时,会分派一个操作。这就是每个组合reducer中提供的初始状态在存储中初始化的方式。如果您检查redux dev工具,您将看到分派的第一个操作是“@@redux/INIT{something}”

在redux的文档中,在文件末尾附近,有一个dispatch({ type: ActionTypes.INIT })

请参见此处https://github.com/reduxjs/redux/blob/master/src/createStore.js#L281-L284

请参见我在stackoverflow上提出的问题/答案,澄清了响应:Different ways of initializing a react redux store's initial global state?


Github的链接已经失效了。你最好链接到实际提交而不是某个分支,因为分支可能会更新。 - gion_13

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接