redux/react 应用程序中的状态有一个带有化简器名称的属性

State in redux/react app has a property with the name of the reducer

本文关键字:属性 有一个 react 应用程序 redux 状态      更新时间:2023-09-26

我正在使用Redux和React创建一个应用程序。我遇到了一个问题,我无法将状态映射到组件属性,因为状态具有与我使用的化简器名称匹配的属性。

根化简器是用combineReducers方法创建的

const rootReducer = combineReducers({
  appReducer
});

初始状态为

const initialState = {
  sources: [], 
  left: {}, 
  right: {},
  diff: {} 
}

但是在组件函数中mapStateToProps

function mapStateToProps(state) {
  return {
    sources: state.sources
  }
}

state.sources undefined,因为state参数的值为

{
  appReducer: {
    sources: [], 
    left: {}, 
    right: {}, 
    diff: {}
  }
}

这是 redux 的一个功能吗?那么当我使用更多的化简器时,它们都会state变量添加新属性吗?还是我这边出了什么问题(我从未在 redux 教程中注意到这种行为)。

谢谢

如果你只有一个减速器,你不需要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
  }
}

现在,您可以使用该化简器创建商店:

import { createStore } from 'redux'
const store = createStore(app)

并将组件连接到它:

const mapStateToProps = (state) => ({
  sources: state.sources
})

但是,您的减速器很难阅读,因为它一次更新许多不同的内容。现在,这是您想要将其拆分为几个独立化简器的时刻:

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),
  }
}

这更容易维护和理解,也更容易独立更换和测试减速器。

最后,

作为最后一步,我们可以使用 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
})

使用 combineReducers() 而不是手动编写根化简器没有太大的好处,除了它的效率稍微高一些,并且可能会为您节省一些拼写错误。此外,您可以在应用中多次应用此模式:可以以嵌套方式将不相关的化简器多次组合到单个化简器中。

所有这些重构都不会对组件产生影响。

我建议您观看我在Redux上的免费Egghead课程,该课程涵盖了这种减速器组合模式,并展示了combineReducers()是如何实现的。

实际上,我相信您的初始状态是:

{
  appReducer: {
    sources: [],
    left: {},
    right: {},
    diff: {}
  }
}

这是因为combineReducers通过采用化简器的名称并将其内容映射到该名称来工作。

另外,只是一个注释,但是如果您要使用多个化简器,则化简器的名称应该比appReducer更具体,并且(仅我个人的意见)它们不需要reducer这个词。典型的应用可能如下所示:

combineReducers({
  user: userReducer,
  messages: messagesReducer,
  notifications: notificationsReducer
});

然后,可以像以下方式访问您的状态:

state.user.email
state.messages[0]
相关文章: