React Hook介绍与使用心得

React Hook介绍与使用心得,第1张

React Hook 对于React来说无疑是一个伟大的特性,它将React从类组件推向了函数组件,从而让人们对于JavaScript的理解不再去可以理解晦涩的JS中的类,以及难以琢磨的this。在《你不知道的JavaScript》上卷中,作者就对JavaScript中的类,继承,面向对象做了一定的解释,总的来说就是,在JavaScript中生搬硬套用面向对象,得不偿失,很容易造成学习和理解负担。

在React16之前没有Hook的时候,必须在类组件去维护组件状态,因此必须理解JS中this的工作机制,并且在给元素绑定事件的时候总是需要绑定this。在组件之间复用状态逻辑比较困难,官方提供的 render props 和 高阶组件 确实很好用,但是整个用起来感觉很重,具体关于对类组件的吐槽可以参考React官网 Hook简介 这部分内容。

当使用React Hook去写React应用后,会发现再也不想用类组件了。。。

官方是这么介绍Hook的: Hook 是 React 168 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

在React中提供了以下几种Hook

示例:

将useState这个钩子从react中导入,在函数组件Login中利用解构赋值的方式声明两个常量 num , setNum 作为 useState(0) 的返回值,useState钩子返回一个数组,第一个参数是我们声明的 state变量 ,第二个参数是一个 方法 ,用来手动改变第一个参数。

语法: const [num, setNum] = useState(0)

useState接受参数为基本类型如数字字符串等,也可以是引用类型对象数组等。用来作为初始值。

关于 useState返回值的第二个参数

示例:

官网这么说:如果你熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做 componentDidMount , componentDidUpdate 和 componentWillUnmount 这三个函数的组合。

useEffect接收一个 函数 为第一个参数。

关于useEffect 这个Hook,它的形式有以下几种:

说了这么多那到底什么是 副作用

React官网是这样解释的:数据获取,设置订阅以及手动更改 React 组件中的 DOM 都属于副作用。不管你知不知道这些 *** 作,或是“副作用”这个名字,应该都在组件中使用过它们。

也就是说,当函数在运行的过程中对外部环境造成影响,或者与外部环境发生交互。比如 *** 作DOM,发起请求,设置订阅这种,都属于副作用。同时有些副作用需要清除,比如订阅解绑,定时器延时器清除,有些不需要清除,比如数据获取, *** 作DOM。

那什么样的函数没有副作用呢?纯函数是不会有副作用的。

在使用useEffect hook的时候可以使用多个Effect分离关注点:

举一个场景来说下:d窗场景。在父组件中点击按钮打开d窗,在d窗内部点击关闭按钮关闭d窗。

此时控制d窗打开与关闭的只能是一个状态isOpen,此时这个isOpen状态就需要在字符组件中共享。

使用isOpen控制d窗的显示与隐藏,在父组件中调用setIsOpen方法,打开d窗,在d窗组件中使用useContext共享的父组件中的方法setIsOpen关闭d窗。

注:父子组件一般不会存在一个文件中,需要将popContext导出再在子组件中导入使用。

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

示例:

useReducer第一个参数是一个reducer函数,第二个参数是初始化状态,在reducer函数中根据不同的type对state进行不同的处理。类似于redux中的reducer。

useRef 返回一个可变的 ref 对象,其 current 属性被初始化为传入的参数( initialValue )。返回的 ref 对象在组件的整个生命周期内保持不变。

这个看来有两种用法:

第一种就是命令式 *** 作DOM元素

第二种是关于其另外一个特性变更 current 属性不会引发组件重新渲染

使用 myRefcount 来统计组件渲染次数。每一次组件重新渲染的时候,都将返回同一个 myRef 对象,并且, myRef 对象发生变化时,并不会导致组件渲染,这样的特性可以用来处理一些特殊场景下的需求。

当自定义一个myRef对象时,每次组件重新渲染都将返回一个新的对象。

这两个Hook可以用来做优化,比如以下例子,有name和age两个状态,子组件只需要在name发生变化时重新渲染,而在age发生变化时不需要重新渲染。

示例:

useMemo第一个参数接收一个函数第二个参数接收一个数组 useMemo(()=>fn, []) ,数组里面是依赖,只有数组里面的依赖发生变化,函数才会执行。

useCallback(fn, deps) 相当于 useMemo(() => fn, deps) 。

React 官方也在极力推动Hook的发展,并且近期也有了React准备重写文档,更新后的文档针对Hook的内容肯定会更多,而且Vue在30版本出来后也使用了类似于React Hook的机制Composition API,这也是一个趋势。

最近在用webpack4+react16+ts4做自己的一个移动端小博客,功能正在完善中,主要是想学习使用一下React技术栈,期间发现React Hook确实非常好用,因此做一些记录。

博客 github 地址: >

接收一个(state, action)=>newState的reducer,返回当前state及配套dispatch

优势:

1、处理复杂逻辑的state及state间有依赖的

2、给那些触发深更新的组件做新能优化;因为 你可以向子组件传递 dispatch 而不是回调函数 ;也就是如何避免向下传递回调?

在大型的组件树中,我们推荐的替代方案是通过 context 用 useReducer 往下传一个 dispatch 函数

React 会确保 dispatch 函数的标识是稳定的,并且不会在组件重新渲染时改变;

初始化useReducer的state:

1、将初始 state 作为第二个参数传入 useReducer 是最简单的方法;React 不使用 state = initialState 这一由 Redux 推广开来的参数约定。

2、 惰性初始化 :需要将 init 函数作为 useReducer 的第三个参数传入,这样初始 state 将被设置为 init(initialArg);这么做可以将用于计算 state 的逻辑提取到 reducer 外部,这也为将来对重置 state 的 action 做处理提供了便利

跳过dispatch

如果 Reducer Hook 的返回值与当前 state 相同,React 将跳过子组件的渲染及副作用的执行。(React 使用 Objectis 比较算法 来比较 state。)

需要注意的是,React 可能仍需要在跳过渲染前再次渲染该组件。不过由于 React 不会对组件树的“深层”节点进行不必要的渲染,所以大可不必担心。如果你在渲染期间执行了高开销的计算,则可以使用 useMemo 来进行优化。

===============================================

解决的问题:

可以在函数组件中添加state而不必转换成class组件

该使用单个还是多个state变量?

1、如果使用单个state变量,需要手动合并

function handleWindowMouseMove(e) {

// 展开 「state」 以确保我们没有 「丢失」 width 和 height

setState(prevState => ({ prevState, left: epageX, top: epageY }));

}

2、或者可以拆分成多个state变量

const [position, setPosition] = useState({ left: 0, top: 0 });

const [size, setSize] = useState({ width: 100, height: 100 });

useState特点:

1、调用 useState 方法的时候做了什么 它定义一个 “state 变量”,和class里的state功能相同,函数退出后state会被React保留,而不会消失;

2、useState的参数就是初始state,class中的state是个对象,而useState中的state可以是数字、字符串、对象;

3、sueState的返回值为当前state以及更新state的函数,与class 的区别是要成对的获取

4、class中的thisstate是合并,而hooks中的state是替换

为什么叫useState而不是createState

1、create可能不准确,因为state只在组件首次渲染的时候被创建,在下次重新渲染时,useState返回给我们当前的state。这个也是hook的名字总是以use开头的原因;

2、我们将在后面的 Hook 规则 中了解原因。

3、你可能会好奇 React 怎么知道 useState 对应的是哪个组件,因为我们并没有传递 this 给 React。我们将在 FAQ 部分回答 这个问题 以及许多其他问题

React 保持对当先渲染中的组件的追踪。多亏了 Hook 规范 ,

每个组件内部都有一个「记忆单元格」列表。它们只不过是用来存储一些数据的 JavaScript 对象。当你用 useState() 调用一个 Hook 的时候,它会读取当前的单元格(或在首次渲染时将其初始化),然后把指针移动到下一个。这就是多个 useState() 调用会得到各自独立的本地 state 的原因

==============

区别:如果修改规则比较复杂,那么将复杂规则放在reducer中使用useReducer比较合适,如果使用的规则比较简单,则可以使用useState的更新state函数中

react的hooks相当于在函数组件中注入了一些能力使其拥有和之前class一样的能力甚至更high

stateHook

    引入statehook

    定义state和处理函数

    读取state

    更新state

useEffect(在渲染或销毁后更新回调,多次定义依次调用)

     引入useEffect

    根据写法,react将自动帮我们识别回调时机

    当某个或多个值在渲染后不希望其更新,则只指定需要react监听的值去跳过其他值的变化回调

useContext

        引入useContext

        创建context

        向子组件提供context

        子孙组件使用

useRef

        引入useRef

        创建ref

        注册ref

        使用ref

示例

以上就是关于React Hook介绍与使用心得全部的内容,包括:React Hook介绍与使用心得、从0搭建React+antd+TypeScript+Umi Hooks+Mobx前端框架、useReducer 和 useState等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9607115.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-30
下一篇2023-04-30

发表评论

登录后才能评论

评论列表(0条)

    保存