我目前使用一个减速器创建我的商店,该减速器已经传递了初始状态。
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')
)
现在我想使用另一个reducer,因为我试图在我的项目中包含Apollo。根据{{3}},我需要结合使用减少器:即
combineReducers({
todos: todoReducer,
users: userReducer,
apollo: client.reducer(),
}),
所以我需要做这样的事情:
const store = createStore(
combineReducers({
apollo: client.reducer(),
reducer: reducers
}),
initialState,
compose(...enhancers)
)
但是我的reducer函数不再具有访问状态的权限(它是未定义的)。当我使用combineReducers时,如何确保传递?
解决方案:
根据Daniel Rearden的建议,我需要将减速器的钥匙与我的初始状态相匹配。
我的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的页面切片。
答案 0 :(得分:3)
之所以没有按照您的预期工作,是因为您改变了州的结构,以及传递给原始缩减器的内容。在您的商店看起来像这样的地方之前:
{
loadUI: true
isNoMatch: false
}
现在,你基本上告诉Redux寻找:
{
apollo: {
// ✁
}
reducers: {
loadUI: true
isNoMatch: false
}
}
当你使用combineReducers时,你实际上是为你的状态创建了孤立的域 - 而不是将整个状态传递给每个reducer,redux只会将状态的一部分传递给每个reducer,而reducer只能通过改变那片状态。通过如上所示构建您的商店,您已经告诉redux只将状态的apollo
切片传递给apollo reducer ...并将状态的reducers
部分传递给原始的reducer。 / p>
我猜你没有对preloadedState
做任何改动。所以正在发生的事情是,redux正在寻找preloadedState
中名为reducers
的属性,并将其传递给您的Reducer。它找不到一个,所以它传递未定义。
这里最简单的解决方法是首先选择比reducers
更具描述性的内容 - ui
?相应地更改combineReducers。然后更新您的preloadedState
,以便您拥有的任何初始状态都嵌套在ui
中。然后它应该按预期工作。请记住,您还需要更新选择器和/或mapStateToProps函数!
修改:您可能希望详细了解combineReducers的工作原理here。