以下介绍的 Hook,有些是上一节中基础 Hook 的变体,有些则仅在特殊情况下会用到。

useReducer

const [state, dispatch] = useReducer(    reducer,    initialArg, init
);

useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。(如果你熟悉 Redux 的话,就已经知道它如何工作了。)

在某些场景下,useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递 dispatch 而不是回调函数 。

以下是用 reducer 重写 useState 一节的计数器示例:

const initialState = {count: 0};   function reducer(state, action) {   switch (action.type) {  case 'increment': return {count: state.count + 1};   case 'decrement': return {count: state.count - 1};    default:    throw new Error();  }
}   function Counter() {    const [state, dispatch] = useReducer(reducer, initialState);   return (    <>    Count: {state.count}    <button onClick={() => dispatch({type: 'increment'})}>+</button>    <button onClick={() => dispatch({type: 'decrement'})}>-</button> </>   );
}

指定初始 state

有两种不同初始化 useReducer state 的方式,你可以根据使用场景选择其中的一种。将初始 state 作为第二个参数传入 useReducer 是最简单的方法:

const [state, dispatch] = useReducer(  reducer,    {count: initialCount}   );

注意 React 不使用 state = initialState 这一由 Redux 推广开来的参数约定。有时候初始值依赖于 props,因此需要在调用 Hook 时指定。如果你特别喜欢上述的参数约定,可以通过调用 useReducer(reducer, undefined, reducer) 来模拟 Redux 的行为,但我们不鼓励你这么做。

惰性初始化

你可以选择惰性地创建初始 state。为此,需要将 init 函数作为 useReducer 的第三个参数传入,这样初始 state 将被设置为 init(initialArg)

这么做可以将用于计算 state 的逻辑提取到 reducer 外部,这也为将来对重置 state 的 action 做处理提供了便利:

function init(initialCount) {   return {count: initialCount};
}   function reducer(state, action) {   switch (action.type) {  case 'increment': return {count: state.count + 1};   case 'decrement': return {count: state.count - 1};    case 'reset': return init(action.payload);    default:    throw new Error();  }
}   function Counter({initialCount}) {  const [state, dispatch] = useReducer(reducer, initialCount, init); return (    <>    Count: {state.count}    <button  onClick={() => dispatch({type: 'reset', payload: initialCount})}> Reset   </button> <button onClick={() => dispatch({type: 'increment'})}>+</button>    <button onClick={() => dispatch({type: 'decrement'})}>-</button> </>   );
}   function render () {    ReactDOM.render(<Counter initialCount={0} />, document.getElementById('root'));
}

我们使用 useReducer 和使用 redux 十分类似,设计思想都是大同小异。

原理

let memoizedState;
function useReducer(reducer, initialArg, init) {    let initState = void 0;    if (typeof init !== 'undefined') {  initState = init(initialArg)   } else {    initState = initialArg }   function dispatch(action) { memoizedState = reducer(memoizedState, action) render()    }   memoizedState = memoizedState || initState return [memoizedState, dispatch]
}   function useState(initState) {  return useReducer((oldState, newState) => newState, initState)
}

useReducer 是 useState 的内部实现

useReducer使用和原理相关推荐

  1. jsbridge原理_React Hooks 原理与最佳实践

    1. 前言 React Hooks 是 React 16.8 引入的新特性,允许我们在不使用 Class 的前提下使用 state 和其他特性.React Hooks 要解决的问题是状态共享,是继 r ...

  2. react文字滚动插件_【赠书】Preact(React)核心原理详解

    豆皮粉儿们,又见面了,今天这一期,由字节跳动数据平台的"winge(宝丁)",带大家见识见识前端"轮子"之一Preact框架. 提到Preact,你肯定会先想到 ...

  3. react 流程图框架_【赠书】Preact(React)核心原理详解Preact(React) 核心原理解析...

    豆皮粉儿们,又见面了,今天这一期,由字节跳动数据平台的"winge(宝丁)",带大家见识见识前端"轮子"之一Preact框架. 提到Preact,你肯定会先想到 ...

  4. 从Preact学习hooks原理--useState

    什么是Preact Preact可以理解为体积更小的react,实现了react的大部分功能,源码相对于react比较简单.Preact也实现了react中的hooks的内容,所以本文从Preact中 ...

  5. 手写Hooks核心原理

    手写实现useState useEffect useReducer 一. useState 钩子函数的实现原理 // import { useState } from 'react' import R ...

  6. Preact(React)核心原理详解

    原创: 宝丁 玄说前端 本文作者:字节跳动 - 宝丁 一.Preact 是什么 二.Preact 和 React 的区别有哪些? 三.Preact 是怎么工作的 四.结合实际组件了解整体渲染流程 五. ...

  7. 【送书】Preact(React)核心原理详解

    本文作者:字节跳动 - 宝丁 本来有个赠书活动,上篇文章忘记发了,重新编辑一下. 本次活动力度空前,参与活动方法见文末. ---------------------------- 一.Preact 是 ...

  8. fragment的工作原理_Preact(React)核心原理详解

    原创: 宝丁 玄说前端 本文作者:字节跳动 - 宝丁 ---------------------------- 一.Preact 是什么 二.Preact 和 React 的区别有哪些? 三.Prea ...

  9. 浅析React Hooks原理

    React Hooks 简介 React Hooks 是 React 16.8 以及之后版本的产物,React Hooks 就是一堆钩子函数,不同的钩子函数提供了不同的功能,React 通过这些钩子函 ...

最新文章

  1. java窗口课程_课程登记窗口java
  2. shell 命令行实现
  3. web前端html图片轮播,如何使用LayUI实现网页轮播图_WEB前端开发,layui,轮播图
  4. CC1101、SI4432、SI4463 相互通信的可能性与得失探讨
  5. [Kali][VMware][2020][窗口大小][分辨率]高分辨率自适应
  6. 文本相似度、文本匹配、文本聚类
  7. leetcode - 392. 判断子序列
  8. akka balance router的实现
  9. 89C52定时/计数器
  10. Jquery获取web窗体关闭事件,排除刷新页面
  11. SQL Server 本机 Web 服务的使用方案(转载)
  12. CAD插件学习系列教程(五) 小菜选择易
  13. 网络编程笔记之TCP例子(帅帅老师讲堂)
  14. 基于Paragraph-BERT-CRF的科技论文摘要语步功能信息识别方法研究
  15. 基于阿里云 OSS 下载图片跨域问题
  16. 大学计算机专业的同学是怎么学习的?
  17. 前后端分离 Spring Boot + Vue 开发网易云、QQ音乐(附源码)!
  18. 什么是Memcached?
  19. H2数据库入门,看这篇就对了
  20. ai人工智能大爆发_人工智能解释了大爆炸之前发生的事情

热门文章

  1. 两万字 40 张图带你参透并发编程
  2. 老板:kill -9 的原理都不知道就敢在线上执行?
  3. 4 月 29 日晚 8 点,为你揭秘联邦学习背后数据可用不可见的奥秘
  4. 微信上线「行程查询」服务;钉钉 CEO 回应被打「一星」;Go 1.14 发布 | 极客头条...
  5. 惊!程序员真的把地府后台管理系统做出来了!
  6. 为什么 SQL 程序员也要懂 Python?
  7. 扎心!新浪年度报告:90后程序员月薪2万,没女朋友
  8. 电信、联通合建 5G,将会碰出怎样的火花?
  9. Java 8 之后,还有哪些进化的功能?
  10. Erlang 二十年,如何在编程语言中占据一席之地?