useReducer使用和原理
以下介绍的 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使用和原理相关推荐
- jsbridge原理_React Hooks 原理与最佳实践
1. 前言 React Hooks 是 React 16.8 引入的新特性,允许我们在不使用 Class 的前提下使用 state 和其他特性.React Hooks 要解决的问题是状态共享,是继 r ...
- react文字滚动插件_【赠书】Preact(React)核心原理详解
豆皮粉儿们,又见面了,今天这一期,由字节跳动数据平台的"winge(宝丁)",带大家见识见识前端"轮子"之一Preact框架. 提到Preact,你肯定会先想到 ...
- react 流程图框架_【赠书】Preact(React)核心原理详解Preact(React) 核心原理解析...
豆皮粉儿们,又见面了,今天这一期,由字节跳动数据平台的"winge(宝丁)",带大家见识见识前端"轮子"之一Preact框架. 提到Preact,你肯定会先想到 ...
- 从Preact学习hooks原理--useState
什么是Preact Preact可以理解为体积更小的react,实现了react的大部分功能,源码相对于react比较简单.Preact也实现了react中的hooks的内容,所以本文从Preact中 ...
- 手写Hooks核心原理
手写实现useState useEffect useReducer 一. useState 钩子函数的实现原理 // import { useState } from 'react' import R ...
- Preact(React)核心原理详解
原创: 宝丁 玄说前端 本文作者:字节跳动 - 宝丁 一.Preact 是什么 二.Preact 和 React 的区别有哪些? 三.Preact 是怎么工作的 四.结合实际组件了解整体渲染流程 五. ...
- 【送书】Preact(React)核心原理详解
本文作者:字节跳动 - 宝丁 本来有个赠书活动,上篇文章忘记发了,重新编辑一下. 本次活动力度空前,参与活动方法见文末. ---------------------------- 一.Preact 是 ...
- fragment的工作原理_Preact(React)核心原理详解
原创: 宝丁 玄说前端 本文作者:字节跳动 - 宝丁 ---------------------------- 一.Preact 是什么 二.Preact 和 React 的区别有哪些? 三.Prea ...
- 浅析React Hooks原理
React Hooks 简介 React Hooks 是 React 16.8 以及之后版本的产物,React Hooks 就是一堆钩子函数,不同的钩子函数提供了不同的功能,React 通过这些钩子函 ...
最新文章
- java窗口课程_课程登记窗口java
- shell 命令行实现
- web前端html图片轮播,如何使用LayUI实现网页轮播图_WEB前端开发,layui,轮播图
- CC1101、SI4432、SI4463 相互通信的可能性与得失探讨
- [Kali][VMware][2020][窗口大小][分辨率]高分辨率自适应
- 文本相似度、文本匹配、文本聚类
- leetcode - 392. 判断子序列
- akka balance router的实现
- 89C52定时/计数器
- Jquery获取web窗体关闭事件,排除刷新页面
- SQL Server 本机 Web 服务的使用方案(转载)
- CAD插件学习系列教程(五) 小菜选择易
- 网络编程笔记之TCP例子(帅帅老师讲堂)
- 基于Paragraph-BERT-CRF的科技论文摘要语步功能信息识别方法研究
- 基于阿里云 OSS 下载图片跨域问题
- 大学计算机专业的同学是怎么学习的?
- 前后端分离 Spring Boot + Vue 开发网易云、QQ音乐(附源码)!
- 什么是Memcached?
- H2数据库入门,看这篇就对了
- ai人工智能大爆发_人工智能解释了大爆炸之前发生的事情
热门文章
- 两万字 40 张图带你参透并发编程
- 老板:kill -9 的原理都不知道就敢在线上执行?
- 4 月 29 日晚 8 点,为你揭秘联邦学习背后数据可用不可见的奥秘
- 微信上线「行程查询」服务;钉钉 CEO 回应被打「一星」;Go 1.14 发布 | 极客头条...
- 惊!程序员真的把地府后台管理系统做出来了!
- 为什么 SQL 程序员也要懂 Python?
- 扎心!新浪年度报告:90后程序员月薪2万,没女朋友
- 电信、联通合建 5G,将会碰出怎样的火花?
- Java 8 之后,还有哪些进化的功能?
- Erlang 二十年,如何在编程语言中占据一席之地?