# redux

react2.jpg

back

# 基础知识

back

Redux 基于三大原则来处理数据流:

# 存储

存储(Store)也被称为单一可信源(single source of truth)。
它在本质上只是你以某种状态初始化的对象,然后每当我们要更新它时,我们都会用新版本覆盖原有的存储。总之,你可能已经在 React 应用中用到了这些理论,通常人们认为最佳实践是重新创建状态而不是突变它。为了进一步解释这种区别我们举个例子,如果我们有一个数组,并且想要将一个新项目推送进去,我们更新存储时不会直接把新项目塞进去,而是会用包含新项目的数组新版本覆盖原来的存储。

# 减速器

于是,我们的存储是通过“减速器”(Reducer)更新的。
这些基本上就是我们发送新版本状态的机制。可能有点不知所云,我们详细说明一下。
假设我们有一个存储对象,它的数组看起来像这样:list: [{‘id: 1, text: ‘clean the house’}]。如果我们有一个将新项目添加到数组中的函数,那么我们的减速器将向存储解释新版本的存储具体是什么样子的。因此考虑这个 list 数组的情况,我们就会获取 list 的内容,并通过...语法将其与要添加的新项目一起传播到新的 list 数组中。因此,我们用来添加新项目的 reducer 应该是这个样子的:list: [...list, newItem]。所以前面我们说要为存储创建状态的新副本,而不是将新项目推送到现有的存储上,就是这个意思。

# 动作

现在,为了让减速器知道要放入哪些新数据,他们需要访问负载(payload)。这个负载通过所谓"动作"(Action)的操作发送到减速器。就像我们创建的所有函数一样,动作通常可以在应用的组件内通过 props 访问。因为这些动作位于我们的组件中,所以我们可以向它们传递参数——也就是负载

# 解释下这些样板是做什么的

应用的根文件 main.js

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import configureStore from "./redux/store/configureStore";
import App from "./App";
const store = configureStore();

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);
1
2
3
4
5
6
7
8
9
10
11
12
13

根 App 中代码:

import React from "react";
import { connect } from "react-redux";
import appActions from "./redux/actions/appActions";
import ToDo from "./components/ToDo";
import "./App.css";

const App = (props) => {
  return <ToDo {...props} />;
};

const mapStateToProps = (state) => {
  return {
    list: state.appReducer.list,
  };
};

const mapDispatchToProps = {
  ...appActions,
};

export default connect(mapStateToProps, mapDispatchToProps)(App);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

前面提到的如何为组件提供对存储的访问权限吗?这就是第二个导入,connect的用途。
mapStateToProps从存储中获取状态,并将其向下传递为连接的 App 组件的 prop
mapDispatchToProps 是一个普通对象,它将获取我们将要创建的 动作 并将它们作为 props 传递到我们连接的 App 组件中

# 错误集锦

# Reducer may not dispatch actions

if (isDispatching) {
  throw new Error("Reducers may not dispatch actions.");
}
1
2
3

当 isDispatching 为 true 的时候会抛出这个错误,然后可以看到当每 dispatch 的时候会走下面 try 将 isDispatching 置为 true 通过 currentReducer 和 action,更新当前的 store tree,只有在 finally 才会将 isDispatching 置为 false,所以当再次 dispatch 的时候,因为该状态还是 true,故抛出了这个错误。