Redux笔记

832 阅读4分钟
原文链接: blog.csdn.net

需要安装的库

npm install –save redux
npm install –save React-redux
npm install –save redux-thunk
npm install –save redux-logger

使用redux的场景

  • 某个组件的状态,需要共享
  • 某个状态需要在任何地方都可以拿到
  • 一个组件需要改变全局状态
  • 一个组件需要改变另一个组件的状态

设计思想

  1. Web 应用是一个状态机,视图与状态是一一对应的。
  2. 所有的状态,保存在一个对象里面。

基本概念

Store

Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。
Redux 提供createStore这个函数,用来生成 Store。
当前时刻的 State,可以通过store.getState()拿到。

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

Action

Action 就是 View 发出的通知,表示 State 应该要发生变化了。 Action 描述当前发生的事情。改变 State 的唯一办法,就是使用 Action。它会运送数据到 Store。

const action = {
  type: 'ADD_TODO',
  payload: 'Learn Redux'
};

Reducer

Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。 Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

const defaultState = 0;
const reducer = (state = defaultState, action) => {
  switch (action.type) {
    case 'ADD':
      return state + action.payload;
    default: 
      return state;
  }
};

const state = reducer(1, {
  type: 'ADD',
  payload: 2
});

实际应用中,Reducer 函数不用像上面这样手动调用,store.dispatch方法会触发 Reducer 的自动执行。为此,Store 需要知道 Reducer 函数,做法就是在生成 Store 的时候,将 Reducer 传入createStore方法。

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

combineReducers方法

Redux 提供了一个combineReducers方法,用于 Reducer 的拆分。你只要定义各个子 Reducer 函数,然后用这个方法,将它们合成一个大的 Reducer。 这种写法有一个前提,就是 State 的属性名必须与子 Reducer 同名。

中间件与异步操作

import { applyMiddleware, createStore } from 'redux';
import createLogger from 'redux-logger';
const logger = createLogger();

const store = createStore(
  reducer,
  applyMiddleware(logger)
);

redux-logger提供一个生成器createLogger,可以生成日志中间件logger。然后,将它放在applyMiddleware方法之中,传入createStore方法,就完成了store.dispatch()的功能增强。 有的中间件有次序要求,使用前要查一下文档。比如,logger就一定要放在最后,否则输出结果会不正确。

数据流

React-Redux 的用法

UI 组件和容器组件

react-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(Container component)。
UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。
UI组件:
- 只负责 UI 的呈现,不带有任何业务逻辑
- 没有状态(即不使用this.state这个变量)
- 所有数据都由参数(this.props)提供
- 不使用任何 Redux 的 API

容器组件:
- 负责管理数据和业务逻辑,不负责 UI 的呈现
- 带有内部状态
- 使用 Redux 的 API

如果一个组件既有 UI 又有业务逻辑,将它拆分成下面的结构:外面是一个容器组件,里面包了一个UI 组件。前者负责与外部的通信,将数据传给后者,由后者渲染出视图。 React-Redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。

connect()

connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来。 任何一个从 connect() 包装好的组件都可以得到一个 dispatch 方法作为组件的 props,以及得到全局 state 中所需的任何内容。

import { connect } from 'react-redux'
const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

为了定义业务逻辑,需要给出下面两方面的信息:
- 输入逻辑:外部的数据(即state对象)如何转换为 UI 组件的参数
- 输出逻辑:用户发出的动作如何变为 Action 对象,从 UI 组件传出去。

mapStateToProps和mapDispatchToProps。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将state映射到 UI 组件的参数(props),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。

mapStateToProps会订阅 Store,每当state更新的时候,就会自动执行,重新计算 UI 组件的参数,从而触发 UI 组件的重新渲染。

如果mapDispatchToProps是一个对象,它的每个键名也是对应 UI 组件的同名参数,键值应该是一个函数,会被当作 Action creator ,返回的 Action 会由 Redux 自动发出。

const mapDispatchToProps = {
  onClick: (filter) => {
    type: 'SET_VISIBILITY_FILTER',
    filter: filter
  };
}

组件

connect方法生成容器组件以后,需要让容器组件拿到state对象,才能生成 UI 组件的参数。 一种解决方法是将state对象作为参数,传入容器组件。但是,这样做比较麻烦,React-Redux 提供Provider组件,可以让容器组件拿到state。

参考文章

Redux 入门教程
Redux “使用”教程