React-redux 中动作和动作类型的含义是什么?

问题描述:

现在,如果我想更改 store 中的值,我应该执行以下步骤:

Now if i want to change value in store i should do following steps:

  1. 转到constants/actionTypes 文件,创建一个带有动作类型的行
  2. 转到动作并创建动作函数
  3. 在我使用它的每个组件中,我应该为 mapDispatchToProps 创建一个函数
  4. 在reducer中我应该写一个改变的逻辑

如此复杂的意义何在?如果我只做一个包含改变状态的动作的文件,会不会是错误的?例如:

Whats the point of such complexity? Will it be wrong if i will do just one file with actions which will change the state? For example:

//actions.js

// actions.js

export const setCategories = (payload, setState, currentState) => setState({ categories: payload })
export const addCategory = (payload, setState, currentState) => setState({ categories: [...currentState.category, payload] })

为了让它工作,我可以为所有项目创建几个通用函数

To make it work i can create just couple of universal functions for all projects

1) getActions,它自动收集所有来自actions.js的导出并将它们提供给mapDispatchToProps,所以我们可以在所有组件中编写

1) getActions, which authomaticly collects all exports from actions.js and provide them to mapDispatchToProps, so in all components we could just write

const mapDispatchToProps = getActions

它的代码可以是这样的

//actionsDispatcher.js

// actionsDispatcher.js

import * as actions from 'actions'
const getActions = (dispatch, ownProps) => {
  Object.keys(actions).forEach(actionName => {
    const fn = actions[actionName]
    actions[actionName] = payload => dispatch({ action: fn, payload, type: _.toSnakeCase(actionName) })
  }
  return actions
}

这意味着我们从actions.js传递到dispatch action函数

which means we pass to dispatch the function of action from actions.js

2) setState 与 react 函数类似,但对于 redux state

2) setState which will work similary to react function, but for redux state

然后在reducer函数中我们就对了

then in reducer function we just right

function rootReducer(state = initialState, action) {
  if (action.action) {
    action.action(action.payload, setState, state)
  } 

  // here we make it extandable for ordinary way if required
  if (action.type === '...') {
    // ...  
  }

}

没有别的...

所以问题是这种方法有什么问题,编码人员只需在一个文件actions.js"中编写一个函数,然后从任何组件调用它作为 props.someActionName(someParams) 而不是更改 4 个不同的文件?

So the question is whats wrong in such approach that will require for coder just write a function in one file 'actions.js' and call it from any component as props.someActionName(someParams) instead of changing 4 differents files?

谢谢

Redux 应该让复杂的需求更容易实现,但如果你有简单的需求,那么它会使实现这些需求变得更加复杂.

Redux is supposed to make complex requirements easier to implement but if you have simple requirements then it makes implementing these requirements more complicated.

动机 提到了 CQRS(命令查询职责分离)将您从存储中读取的方式(在带有选择器的 redux 中,我是重新选择的忠实粉丝)与您写入的方式分开它(带有动作和减速器).

The motivation mentions CQRS(Command Query Responsibility Segregation) that separates how you read from store (in redux with selectors and I'm a big fan of reselect) with how you write to it (with action and reducers).

actions 和 reducer 是 CQRS 的命令(写入)部分,是 事件源,redux 有时被称为事件存储.这使您能够为您的事件(动作)添加或删除处理程序(reducer 或中间件),这些处理程序可以更新存储、调度其他事件(=动作)、执行异步操作、写入本地存储.

The actions and reducers are the command (write) part of CQRS and is event sourcing, redux is sometimes referred to as an event store. This enables you to add or remove handlers (reducers or middle ware) for your events (actions) that can update the store, dispatch other events (=actions), do asynchronous stuff, write to local storage.

如果您需要在一个函数中完成所有这些事情(异步获取、写入本地存储、调用其他函数(调度其他操作)等),那么该函数将变得无法管理.

If you need to do all these things in one function (async fetch, write to local storage, call other functions (dispatch other actions),...) then that function becomes unmanageable.

即使函数只调用其他函数,它仍然需要知道某个动作的整个过程.但是,如果(例如)您有一个本地存储中间件,可以在某些操作上写入存储,那么其他代码不需要知道如何或何时调用它.所以当写入本地存储的逻辑发生变化时,仅限于本地存储中间件.

Even if the function only calls other functions then it still needs to know the entire process of certain action. But if (for example) you had a local storage middleware that would write to storage on certain actions then no other code needs to know how or when it's called. So when logic of writing to local storage changes it is limited to the local storage middle ware.

这就是处理程序(reducer、中间件)监听事件(动作)的优势,处理程序只需要知道进程的一小部分,而不是整个进程.

This is the advantage of handlers (reducers, middleware) listening to events (actions), the handler only needs to know about a small portion of the process, not the entire process.

有了事件资源,我们也知道为什么状态有一定的价值,而不是只知道状态是什么,文章 指出:

With event resourcing we also know why the state has a certain value instead of only knowing what the state is, the article states:

然而,有时我们不仅想看看我们在哪里,我们还想知道我们是如何到达那里的.

However there are times when we don't just want to see where we are, we also want to know how we got there.

事件存储的另一大优势是您可以通过回放事件重新创建数据.所有这些都可以通过 redux def 工具出色地完成.

Another big advantage of an event store is that you can re create the data by playing back the events. All this is excellently done with redux def tools.

这里是一本关于 React 和 Redux 的好书.

Here is a great book on React with Redux.