javascript - redux/react 应用程序中的状态有一个名为 reducer 的属性

标签 javascript reactjs state redux

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

root reducer 是用combineReducers 方法创建的

const rootReducer = combineReducers({
  appReducer
});

初始状态为

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

但是在组件函数mapStateToProps中:

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

state.sourcesundefined 因为state 参数的值是

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

这是redux的特性吗?那么当我使用更多的 reducer 时,它们都会向 state 变量添加新的属性吗?还是我这边有问题(我从来没有在 redux 教程中注意到这种行为)。

谢谢

最佳答案

如果您只有一个 reducer ,则不需要 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
  }
}

现在您可以使用该 reducer 创建商店:

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

并将一个组件连接到它:

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

但是你的 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),
  }
}

这样更容易维护和理解,也更容易独立更改和测试 reducer。

最后,作为最后一步,我们可以使用 combineReducers() 生成根 app reducer 而不是手动编写:

// 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() 而不是手动编写 root reducer 并没有太大的好处,除了它稍微更有效率并且可能会避免一些错别字。此外,您可以在您的应用程序中多次应用此模式:以嵌套方式多次将不相关的缩减器组合成单个缩减器是可以的。

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

我建议您观看我的 free Egghead course on Redux其中涵盖了这种reducer 组合 模式,并展示了combineReducers() 是如何实现的。

关于javascript - redux/react 应用程序中的状态有一个名为 reducer 的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35667775/

相关文章:

reactjs - react 组件错误无法读取未定义的属性

javascript - React 前端未与 Spring Boot REST API 通信。控制台 axios 网络错误

c# - 将实体的状态设置为已删除会将实体从 dbContext 中删除

javascript - jQuery 在 ajax 调用后更新 li 类属性 href

javascript - 将 javaScript 数组添加到 HTML 页面?

javascript - readAsText(file) 只读取目录中的最后一个文件

angularjs - 为什么要给 "abstract: true"状态一个 url?

javascript - 如何将JS变量传递给Modal路由

javascript - React.js - 如何停止 setInterval 并在单击后恢复它

ios - 使用 SwiftUI 从 SessionDownloadDelegate 显示进度