Kar*_*ták 15 javascript state reactjs redux
我正在使用Redux和React创建一个应用程序.我遇到一个问题,我无法将状态映射到组件属性,因为状态具有与我使用的reducer的名称匹配的属性.
根减少器是使用combineReducers
方法创建的
const rootReducer = combineReducers({
appReducer
});
Run Code Online (Sandbox Code Playgroud)
最初的状态是
const initialState = {
sources: [],
left: {},
right: {},
diff: {}
}
Run Code Online (Sandbox Code Playgroud)
但是在组件功能中mapStateToProps
:
function mapStateToProps(state) {
return {
sources: state.sources
}
}
Run Code Online (Sandbox Code Playgroud)
这state.sources
是undefined
因为state
参数的值是
{
appReducer: {
sources: [],
left: {},
right: {},
diff: {}
}
}
Run Code Online (Sandbox Code Playgroud)
这是redux的一个特性吗?所以当我使用更多reducers时,所有这些都会为state
变量添加新属性?或者我身边有什么问题(我在redux教程中从未注意到这种行为).
谢谢
Dan*_*mov 28
如果您只有一台减速机,则不需要combineReducers()
.直接使用它:
const initialState = {
sources: [],
left: {},
right: {}
}
function app(state = initialState, action) {
switch (action.type) {
case 'ADD_SOURCE':
return Object.assign({}, state, {
sources: [...state.sources, action.newSource]
})
case 'ADD_SOURCE_TO_LEFT':
return Object.assign({}, state, {
left: Object.assign({}, state.left, {
[action.sourceId]: true
})
})
case 'ADD_SOURCE_TO_RIGHT':
return Object.assign({}, state, {
right: Object.assign({}, state.right, {
[action.sourceId]: true
})
})
default:
return state
}
}
Run Code Online (Sandbox Code Playgroud)
现在您可以使用该reducer创建一个商店:
import { createStore } from 'redux'
const store = createStore(app)
Run Code Online (Sandbox Code Playgroud)
并将组件连接到它:
const mapStateToProps = (state) => ({
sources: state.sources
})
Run Code Online (Sandbox Code Playgroud)
但是你的reducer很难阅读,因为它会同时更新许多不同的东西.现在,这是您想要将其拆分为多个独立Reducer的时刻:
function sources(state = [], action) {
switch (action.type) {
case 'ADD_SOURCE':
return [...state.sources, action.newSource]
default:
return state
}
}
function left(state = {}, action) {
switch (action.type) {
case 'ADD_SOURCE_TO_LEFT':
return Object.assign({}, state, {
[action.sourceId]: true
})
default:
return state
}
}
function right(state = {}, action) {
switch (action.type) {
case 'ADD_SOURCE_TO_RIGHT':
return Object.assign({}, state, {
[action.sourceId]: true
})
default:
return state
}
}
function app(state = {}, action) {
return {
sources: sources(state.sources, action),
left: left(state.left, action),
right: right(state.right, action),
}
}
Run Code Online (Sandbox Code Playgroud)
这更易于维护和理解,并且还可以更轻松地独立更改和测试减速器.
最后,作为最后一步,我们可以使用combineReducers()
生成根app
减速器而不是手动编写它:
// function app(state = {}, action) {
// return {
// sources: sources(state.sources, action),
// left: left(state.left, action),
// right: right(state.right, action),
// }
// }
import { combineReducers } from 'redux'
const app = combineReducers({
sources,
left,
right
})
Run Code Online (Sandbox Code Playgroud)
使用combineReducers()
而不是手动编写根减速器没有什么大的好处,除了它稍微更有效并且可能为您节省一些拼写错误.此外,您可以在应用程序中多次应用此模式:将不相关的Reducer以嵌套方式多次组合到单个reducer中可以.
所有这些重构都不会对组件产生影响.
我建议你在Redux上观看我的免费Egghead课程,该课程涵盖了这种减速器组成模式,并展示了如何combineReducers()
实现.
实际上,我相信你的初始状态是:
{
appReducer: {
sources: [],
left: {},
right: {},
diff: {}
}
}
Run Code Online (Sandbox Code Playgroud)
这是因为combineReducers
通过获取reducer的名称并将其内容映射到该名称来工作.
另外,只是一个注释,但如果你要使用超过1个减速器,你的减速器的名称应该更具体appReducer
,并且(仅我的个人意见)他们不需要这个词reducer
.典型的应用程序可能如下所示:
combineReducers({
user: userReducer,
messages: messagesReducer,
notifications: notificationsReducer
});
Run Code Online (Sandbox Code Playgroud)
然后,可以访问您的州:
state.user.email
state.messages[0]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
6422 次 |
最近记录: |