Skip to content

Instantly share code, notes, and snippets.

@tylerlong
Last active October 16, 2016 09:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tylerlong/a906f72029ed14c8c5ca77b77f6c436d to your computer and use it in GitHub Desktop.
Save tylerlong/a906f72029ed14c8c5ca77b77f6c436d to your computer and use it in GitHub Desktop.
React & Redux

React & Redux 学习笔记 - 第一篇:术语浅析

这是 React & Redux 学习笔记 系列文章的第一篇。这篇主要分析各种术语。参考来自各种技术官网的文档,夹杂了笔者的个人体会和理解。

文章分为两部分,第一部分讲 React 相关的术语,第二部分讲 Redux 相关的术语。每一部分都把相对最重要的术语放在了前面。

通过阅读这篇文章,读者可以全面掌握各种核心 React & Redux 术语。 在听别人讨论相关技术问题的时候,能够及时进入语境,理解别人谈话的内容,不再如闻天书、不知所以。

由于术语数量比较多,一下子记不住也没关系。可以在碰到相关术语的时候,来这里查一下。

第一部分:React

React 是 Facebook 出品的用来开发用户界面的 JavaScript 库。 React 在 GitHub 上面有5万多颗星, 火热程度可见一斑。React 可能是当前最值得学习的前端技术。

值得一提的是,React 仅仅是一个界面库,它仅仅提供了 MVC 中的 V。对于复杂的应用,多半还需要搭配其它的库一起使用,比如说 Redux。

套用官方的说法,React 要解决的问题是:

building large applications with data that changes over time.

我们能得出结论,React 适用的场景有两个特征:一个是规模比较大;另一个是有较频繁数据更新。

Component

事实上 React 唯一的核心术语就是 component。Component 是封装良好的、可重用的界面元件。React 就是关于构建可重用的 components 的。

可以把 component 看作是 Function,它接受 props 和 state 作为参数,然后输出 render 之后的 HTML。

站在 JSX 的角度,也可以把 component 看作是对 HTML 语法的扩展,比如定义一个叫做 HelloWorld 的 component,可以像这样来使用它: <HelloWorld />

JSX

严格来讲 JSX 并不属于 React。但是 React 是推荐使用 JSX 的,并且官方的例子中,默认也都使用了 JSX。

JSX lets you create JavaScript objects using HTML syntax.

没有 JSX 的情况下,我们只能通过调用 React.createElement 来构建界面。JSX 是对 JS 语法的扩展,通过它写出的界面代码跟 HTML 很像,极大地提高了可读性。

JSX 唯一的问题在于包含了 JSX 代码的 JS 文件没办法直接执行,需要预先编译一下(已经熟练使用 Babel 的同学表示毫无压力)。

Props & State

React 官方文档并没有把这两个词列为术语。简单了解下对于学习有帮助.

Props

Props 是调用 component 的时候传递进去的参数。比如 <HelloWorld key="value" />this.props.key 的值就是 value。 这个概念跟 HTML 的 attributes 很像。需要特别注意的是:props 对于当前 component 来讲是不可变的,不要尝试在 component 内部对其进行修改或赋值。

State

State 代表了 component 的状态。它是可变的。比如你可以像这样修改它:this.setState({key: value});。每次 state 更新,component 会重新 render 它自己。

如果把 component 类比为 Function,不可变的 props 就类似 Function 的参数,Function 内部不能修改参数的值。 可变的 state 就类似 Function 内部声明的变量,Function 可以根据具体情况修改 state 的值来改变自己的返回值(component render() 的结果)。

第二部分:Redux

Redux 在 GitHub 上面有两万多颗星,是最流行的 Flux 实现。 很多人认为,一旦 React 程序变复杂,就要引入 Redux。GitHub 上面很多 React 的项目同时也使用了 Redux。

Redux is a predictable state container for JavaScript apps.

Redux 本质上是 JS 程序中 state 的容器。它通过加入一些限制,使得 state 的修改可预测,可以帮助你写出在不同环境下行为高度一致的程序。

值得一提的是,Redux 和 React 并没有非常直接的关系,React 可以没有 Redux,Redux 也可以和 React 之外的其它 View 框架搭配使用。

State

State 可以是任意类型。但一般情况下,是一个对象,或者是一个 key value 数据结构。

State 应该是能够序列化为 json 的。

State 是被 store 所管理的,代表了整个 Redux 程序的状态。

注意这里讲的是 Redux 的 state,不要和之前的 React 的 state 搞混了。

Action

Action 是一个对象类型,它表达了想要更改 state 的一个 intention。

It's a payload of information

所有的数据都需要通过 action 才能进 store。

Action 必须有 type 字段,一般是 string 类型,其它字段就随意了。

初学者总会觉得 action 是一个函数,其实并不是。这个术语的名字确实有一定的迷惑性。笔者觉得也许叫做 actor 会更好。

Reducer

Reducer 是一个 function。 就是经典的 map / reduce 那个 reduce 的概念。

它接受 state 和 action 作为参数,返回 state。

state is the accumulated value, actions are are values being accumulated.

用一个 Ruby 的例子通俗形象点讲,list.reduce(0) { |sum, item | sum + item }, state 就相当于 sum,action 就相当于 item

因为 reducer 必须是纯函数式的(没有副作用),所以 API call 不能放到里面。

Dispatch(ing) Function

Dispatch(ing) Function 是一个 Function,它接受 (async) action 作为参数,然后它可以把 action dispatch 给 store。具体是否 dispatch,是要看情况的。

这里有两个类似的概念:store 实例的 base dispatch() 和 general 的 dispatch function。 前者只支持sync,但是一些 middleware wrap 它之后给它提供了支持 async 的功能。

我个人理解简化后的工作流程是这样的:dispatch function 先经过 middleware 的 wrap,调用 store 的 base dispatch(), 从 store 获取最新的 state,然后连同 action 一起发送到 reducer,计算出一个新的 state, 再存入 store。

Action Creator

Action Creator 也是一个 Function,用来创建 action 的。感觉像是典型的工厂模式。

它接受的参数个数和类型都是随意的。

Action Creator 只负责 create,不负责 dispatch。如果 create 完马上再调用 store 的 dispatch(),过程被称为是 bound action creators

Action Creator 是可以有副作用的,也可以读取 store 数据或者 API 数据,有副作用的话就只能创建 async action。

Async Action

Async Action 可以是任意类型。这点和 Action 不一样,因为 Action 只能是对象类型。

它将先被发送到 dispatch function, 然后被 middleware 转成一个或者多个 Action,再被发送给 store 的 base dispatch()。

Async Action 经常是 Promise,并不能立刻被发送给 reducer。

Middleware

Middleware 是 high order function。

它接受一个 dispatch function 作为参数,返回新的 dispatch fucntion。

我的理解是,一个 Function 的参数和返回类型都是 Function,那么这个 Function 就是 high order function。

当然 Middleware 的函数签名是很复杂的,远没有上面说的那么简单。感兴趣的话请看下面

type MiddlewareAPI = { dispatch: Dispatch, getState: () => State }
type Middleware = (api: MiddlewareAPI) => (next: Dispatch) => Dispatch

它们经常干的事情就是把 async actions 变成 actions。

Middleware 是 composable 的。(当然了,否则多个 middleware 怎么串联起来?)

Middleware 修改的是 dispatch,而 dispatch 到最后总是要调用 store 的 base dispatch(), 所以你也可以认为 middleware 修改的是 store (的dispatch)。

Store

Store 是一个对象。一个 Redux app 只能有一个 store。Store 有下面四个属性:

  1. dispatch(action) 也就是上面我们提到的 store 的 base dispatch()。
  2. getState() 应该就是一个getter方法,返回 state 对象。
  3. subscribe(listener) 监听者模式。注册监听者,当 state 发生改变的时候被调用。
  4. replaceReducer(nextReducer) 基本上用不到。它可以实现 hot reloading and code splitting。

Store Creator

Store Creator 是一个 Function,顾名思义,就是用来 create store 的。

它接受 Reducer 和 State 作为参数,返回 Store.

这里面有两个类似的概念需要区分,一个是来自 Redux 的 base createStore(reducer, preloadedState),还有一个是 store enhancers 所返回的 store creators。

Dispatch 那里也是有两个类似的概念需要区分。其实这种现象不难理:函数式编程是非常强调 fuction composition 的,一个 function,被其它的 functions compose 几下,生成的 function 名字可能并没有改变,实际上行为和特性已经发生了改变。于是就出现了很多名字类似但又需要区分的概念。

OO 编程折腾数据,FP 编程折腾函数。

Store Enhancer

Store Enhancer 是一个 Function, 并且是 high order function。

它接受一个 Store Creator 作为参数,返回一个 Store Creator。

有意思的是,虽然它的名字叫做 Store Enhancer,它折腾的却是 Store Creator,而不是 Store。

和 Middleware 类似,它也是 composable 的。

由于 Redux 的 Store Enhancer 非常像 React 的 high order components, 所有少数情况下,它也被称作为 component enhancer

最后,很可能你永远都不会自己去写一个 Store Enhancer。所以似乎也不用太深入去了解。

参考资料

写这篇文章的时候参考了如下的文档或文章:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment