Title Text

函数式编程范式

  • 输出完全取决于参数

  • 无副作用 (Immutable)

  • 关注想得到的结果,而不是过程(声明式)

}

纯函数

输出完全取决于参数

(showButton, buttonText) => 
  <div>
    {showButton &&
      <button>
        {buttonText}
      </button>}
  </div>
(showButton) => 
  <div>
    {showButton &&
      <button>
        {localStorage
           .getItem(‘buttonText’)}
      </button>}
  </div>

无副作用

const addItem = (itemList, item) => {
  return [...itemList, item]
}
const addItem = (itemList, item) => {
  itemList.push(item);
  return itemList;
}
const getMessage = async () => {
  const message =
    await get('/api/message');
  return message;
}

声明式

描述我想要的结果是什么

命令式

描述具体怎么做

(showButton) => 
  <div>
    {showButton && <button>click</button>}
  </div>
(showButton, $container) => {
  if (showButton) {
    $container
      .append($('<button>click<button>'));
  } else {
    $container
      .remove('button');
  }
}
const getFields = (items, fieldName) => items
  .filter(item => item[fieldName])
  .sort((a, b) => a[fieldName] - b[fieldName])
  .map(item => item[fieldName])
const getFields = (items, fieldName) => {
  const ret = [];
  for (let i = 0; i < item.length; i++) {
    if (items[i][fieldName]) {
      ret.push(items[i][fieldName])
    }
  }
  return ret;
}

为什么需要纯函数

  • 输出完全取决于参数:可预测,不会被别人影响
  • 无副作用:不会影响别人
  • 以结果为导向,步骤清晰,容易理解
  • 容易测试
  • 可缓存

简单的 React 组件是纯函数

// https://reactjs.org/docs/components-and-props.html

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

复杂的 React 组件不是...

  • 内部 state
  • 副作用 (发送请求,触发事件)
  • PureComponent ≠ pure function

Redux:“纯化”了 React

  • 取消内部状态,输出只由参数(props)决定
  • 状态的变化(reducer)也是纯函数
  • 统一管理副作用(thunk)

Redux State

UI

Reducer

Actions

pure

pure

pure

impure

Redux 的理想模型

  • 所有数据存在 Redux 的 state 里
  • UI 完全由 Redux state 决定(是关于 state 的纯函数)
  • UI 发送事件(action)驱动 Redux state 更新
  • 逻辑独立于 UI

Redux 的理想模型

  • React 组件只包含渲染逻辑 + 事件回调 (hooks, event handlers)。类比 handlebars
  • Action 相当于 event,描述发生了什么,类比 dom event
  • Reducer 包含真正的逻辑
  • Selector 负责数据的转换与组装(同样是纯函数)

现实是...

UI 数据来源与生命周期:

 

Redux state (每次页面刷新)

Component state (每次组件加载)

localStorage / sessionStorage (永久 / 浏览器打开)

cookie (取决于后端设置)

URL (每次 URL 改变)

History state (每次 URL 改变)

deck

By lukeupup

deck

  • 198