如何将初始状态传递给减速器
Posted
技术标签:
【中文标题】如何将初始状态传递给减速器【英文标题】:How to pass initial state to reducer 【发布时间】:2017-12-21 10:00:19 【问题描述】:我目前使用一个将初始状态传递给它的减速器创建我的商店。
import reducers from './reducers'
const store = createStore(
reducers,
initialState,
compose(...enhancers)
)
// reducers.js
export default function reducer(state, action)
console.log('state', state)
switch (action.type)
case 'LOAD_UI':
return Object.assign(, state,
loadUI: action.loaded
);
case 'NO_MATCH':
return Object.assign(, state,
loadUI: true,
isNoMatch: action.isNoMatch
);
default:
return state;
当我在 reducer 函数中记录状态时,我会得到配置存储时设置的状态:
// if we are in production mode, we get the initial state from the window object, otherwise, when we are in dev env we get it from a static file
const preloadedState = window.__INITIAL_STATE__ === '__PRELOADEDSTATE__' ? initialState : window.__INITIAL_STATE__
const store = configureStore(preloadedState)
ReactDOM.render(
<Provider store=store>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
, document.getElementById('root')
)
现在我想使用另一个减速器,因为我试图将 Apollo 包含在我的项目中。根据http://dev.apollodata.com/react/redux.html,我需要组合Reducers:即
combineReducers(
todos: todoReducer,
users: userReducer,
apollo: client.reducer(),
),
所以我需要做这样的事情:
const store = createStore(
combineReducers(
apollo: client.reducer(),
reducer: reducers
),
initialState,
compose(...enhancers)
)
但是我的 reducer 函数不再能够访问状态(它是未定义的)。当我使用 combineReducers 时,如何确保它通过?
解决方案:
根据 Daniel Rarden 的建议,我需要将减速器的键与我的初始状态匹配。
我的 initialState 看起来像:
"pages": [
"id": 5,
"title": "About",
"slug": "about",
"path": "/about",
"template": "about",
"published": "2017-07-10 02:02:30",
"image": null,
"seo":
"title": null,
"description": null,
"image": null,
"fbAdmins": null,
"gtm": null,
"schema": ""
,
"sections": [
]
,
"id": 10,
"title": "Contact",
"slug": "contact",
"path": "/contact",
"template": "contact",
"published": "2017-07-11 04:27:30",
"image": null,
"seo":
"title": null,
"description": null,
"image": null,
"fbAdmins": null,
"gtm": null,
"schema": ""
,
"sections": []
,
"id": 4,
"title": "Home",
"slug": "home",
"path": "/",
"template": "home",
"published": "2017-07-10 01:39:48",
"image": null,
"seo":
"title": null,
"description": null,
"image": null,
"fbAdmins": null,
"gtm": null,
"schema": ""
,
"sections": []
],
"services": [],
"clients": [],
"people": [],
"offices": [],
"articles": [],
"menus":
"header": [
"title": "Home",
"slug": "/"
,
"title": "About",
"slug": "/about"
,
"title": "Contact",
"slug": "/contact"
]
,
"settings":
"site":
"title": null,
"siteUrl": ""
,
"logo": [],
"secondarylogo": [],
"favicon": [],
"disclaimer": null,
"tagline": null,
"social": null,
"email": null,
"phone": null,
"facebookAppId": "",
"seo":
"title": null,
"description": null,
"image": null,
"fbAdmins": null,
"gtm": null,
"schema": ""
,
"newsLetterSignUp":
"image": "",
"title": "",
"content": ""
,
"menu_settings": null
所以我的减速器看起来像这样:
import combineReducers from 'redux'
import ApolloClient from 'react-apollo';
const client = new ApolloClient();
import articles from './articles'
import pages from './pages'
import services from './services'
import clients from './clients'
import people from './people'
import offices from './offices'
import menus from './menus'
import settings from './settings'
export default combineReducers(
apollo: client.reducer(),
articles,
pages,
services,
clients,
people,
offices,
menus,
settings
)
这样我的pages
reducer 只能获取我的 initialState 的页面切片。
【问题讨论】:
【参考方案1】:这没有像您预期的那样工作的原因是您更改了状态的结构,以及传递给原始减速器的内容。你的商店以前是这样的:
loadUI: true
isNoMatch: false
现在,您基本上已经告诉 Redux 寻找:
apollo:
// ✁
reducers:
loadUI: true
isNoMatch: false
当你使用 combineReducers 时,你实际上是在为你的 state 创建隔离域——而不是将整个 state 传递给每个 reducer,redux 只会将 state 的一部分传递给每个 reducer,而 reducer 只能改变那部分状态。通过如上所示构建您的 store,您已经告诉 redux 仅将状态的 apollo
切片传递给 apollo reducer...并将状态的 reducers
部分传递给您的原始 reducer。
我猜你没有对preloadedState
进行任何更改。所以发生的事情是 redux 在 preloadedState
中寻找一个名为 reducers
的属性并将其传递给您的减速器。找不到,所以传入 undefined。
这里最简单的解决方法是,首先,选择比reducers
更具描述性的东西——也许ui
?相应地更改您的 combineReducers。然后更新您的preloadedState
,以便您拥有的任何初始状态都嵌套在ui
中。然后它应该按预期工作。请记住,您还需要更新选择器和/或 mapStateToProps 函数!
编辑:您可能想了解更多关于 combineReducers 的工作原理here。
【讨论】:
谢谢。这值得一读combineReducers
的工作原理。我错过了每个减速器都映射到预加载状态中的键的事实。以上是关于如何将初始状态传递给减速器的主要内容,如果未能解决你的问题,请参考以下文章
reactjs - 如何在formik中将状态值传递给初始值