3-1-Redux 简介

记得在课程开始的时候我们就讲到,我们使用React的主要情境不是内容网页,而是Web应用。Web应用与我们传统的新闻站、博客等类型的网站有很大的不同。Web应用会涉及到非常多的数据交互、异步传输、甚至我们需要让所有的用户交互和应用功能在同一个页面里完成,也就是开发单页面应用。

换句话讲,我们要开发的Web应用会涉及非常多的状态state改变。包括与服务器的数据交互,界面上导航或其他部件的切换、处理用户输入等等。可以想象,等到我们的应用复杂到一定程度时,如果应用的状态分散在各个组件当中,有的组件只控制自己样式改变的状态,有的组件之间需要相互通信,传递数据。各种各样的数据,状态改变错综复杂,后期维护起来简直会是一场噩梦。万一产品经理这时候再提出说要改几个需求,添加个功能,跳楼的心估计都有了。

之前我们介绍过了React当中有状态组件和无状态组件的概念,React本身也推荐我们尽量控制有状态组件的个数,开发过程中我们编写的组件90%都应该是无状态组件,然后通过props来接收数据。

React本身只留给了我们state和props来管理应用数据的状态,context只是实验性质的一种传递数据的方式。也就是说,React本身并没有很好地提供应用状态管理的解决方案,在一些小应用中我们可能感觉不到状态管理是一个问题,但是随着应用的复杂度增加,这个问题会暴露得越来越明显。这时候我们就需要使用到Redux

既然React推荐我们尽量少得编写有状态组件,那么我们何不干脆把一个应用的数据状态统一在一个地方管理?这便是Redux的理念。

Redux把应用的数据统一储存在一个全局对象中。把应用所有的数据交互和状态改变,统一用固定形式的action动作对象来描述。经由名为Reducer的方法来判断不同的动作如何改变应用状态。最后,我们通过Store对象来负责执行action动作,获取state应用状态、订阅状态改变时触发的事件。

// Reducer
const counter = (state = { value: 0 }, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { value: state.value + 1 };
    case 'DECREMENT':
      return { value: state.value - 1 };
    default:
      return state;
  }
}

class Counter extends Component {
  // State
  constructor() {
    super();
    this.state = counter(undefined, {});
  }

  dispatch(action) {
    this.setState(prevState => counter(prevState, action));
  }
  // Actions
  increment = () => {
    this.dispatch({ type: 'INCREMENT' });
  };

  decrement = () => {
    this.dispatch({ type: 'DECREMENT' });
  };

  render() {
    return (
      <div>
        {this.state.value}
        <button onClick={this.increment}>+</button>
        <button onClick={this.decrement}>-</button>
      </div>
    )
  }
}

事实上,Redux提供的更多的是一种应用状态管理问题的解决思路。它的源码很少,只有几kb,我们甚至可以用一些非常基本的函数方法来模拟实现redux的全部功能。并且,即使我们在应用中引入Redux,编写的大部分也都是原生的JS函数和对象而已。也就是说,只要你能够掌握Redux的理念,你甚至无需使用Redux这个库本身,也能够通过它的方式来编写代码解决问题。换句话讲,你可以用自己的代码实现 Redux 的所有核心功能,所以 Redux 也是最适合拿来教学的一个状态管理库。

可能实践中 Redux 在处理数据的流程上有一些繁琐,在对一些比较复杂(例如带有异步)的操作方面比较吃力,但学习 Redux 仍然能让你对应用的状态管理这一方面的功能有一个全面的理解。

在正式开始学习Redux之前,还有一点需要提醒各位同学。任何一个新的框架和库的出现都是为了解决某些或某个特定的问题。我们使用一个框架或库也应该秉持“我是为了解决遇到的问题才使用这个框架或库”的原则。而不是因为某个框架比较流行比较火,在根本没有了解其出现的背景下就开始盲目使用。我们的教程只是为了帮助大家掌握React技术栈的使用方法和理念,而在实际的工作中是否要运用我们了解到的这些工具,还需要具体情况具体分析,等到我们真正遇到了实际的问题时,再拿出相应的库来解决。

要记得,永远不要为了用框架而用框架。本教程的目的也只是为了教给你React主要技术栈的使用方法,并不是告诉你,以后只要开发Web应用就必须使用我们所学的这些工具库,而是在你真正遇到需要这些工具库来解决的问题时再去实际应用。

Last updated