React —— Hook

Hook 是 React 的特性,作用是可以在不编写 Class 的情况下(函数组件)使用 state 以及其他 React 特性。

Hook 使你在无需修改组件结构的情况下复用状态逻辑。

复杂组件的生命周期中可能包含很多逻辑,Hook 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据)

使用class 组件要理解 JavaScript 中 this 的工作方式,Hook 使你在非 class 的情况下可以使用更多的 React 特性。 

React 是如何把对 Hook 的调用和组件联系起来的?

React 保持对当前渲染中的组件的追踪。

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

useState 

做了什么:方括号定义一个 “state 变量”,数组解构-useState 返回的数组中的两个值

当我们更新一个 state 变量,setState 会 替换 它的值。这和 class 中的 this.setState 不一样,后者会把更新后的字段 合并 入对象中。

(如果在一次 useState() 调用中传入一个包含多个 state 的对象。但是只更新其中一部分state 的值,setState 时也需要展开 「...state」 以确保数据的完整,因为setState 是对state 进行替换的操作。 而this.setState 中只需要写更新的那些数据,它会合并到对象中。)

useEffect

componentDidMountcomponentDidUpdate 和 componentWillUnmount 这三个生命周期函数的组合。

如果在组件加载和更新时,即在每次渲染之后执行同样的操作,就要在 componentDidMount (组件加载)和 componentDidUpdate (组件更新)函数中写重复的代码。

与 componentDidMount 或 componentDidUpdate 不同,使用 useEffect 调度的 effect 不会阻塞浏览器更新屏幕,大多数情况下 effect 不需要同步地执行。

两种常见副作用操作:需要清除的和不需要清除的。

不需要清除的:在 React 更新 DOM 之后运行一些额外的代码。比如发送网络请求,手动变更 DOM,记录日志。在执行完这些操作之后,就可以忽略他们了。

需要清除的:如订阅外部数据源,这种操作的清除工作非常重要,防止引起内存泄露。在 componentDidMount 中设置订阅,并在 componentWillUnmount 中清除。

useEffect 做了什么? 告诉 React 组件在渲染后执行某些操作。React 会保存其中传递的函数(我们将它称之为 “effect”),并且在执行 DOM 更新之后调用它。、

在 effect 中返回return一个清除函数, 这是 effect 可选的清除机制,React 会在组件卸载的时候执行清除操作。如此可以将添加和移除订阅的逻辑放在一起。

优点:可以使用多个 effect,将不相关逻辑按照代码的用途分离到不同的 effect 中。

useEffect 默认会在调用一个新的 effect 之前对前一个 effect 进行清理,避免了在 class 组件中因为没有处理更新逻辑而导致常见的 bug。

将 useEffect 放在组件内部让我们可以在 effect 中直接访问 count state 变量(或其他 props)。(Hook 使用了 JavaScript 的闭包机制)

通过跳过 Effect 进行性能优化

仅在指定变量更改时,调用effect:将指定变量以数组形式 作为 useEffect 的第二个可选参数。组件重渲染时,如果数组中的所有元素都与原来相等,React 就会跳过这个 effect,从而实现了性能的优化。即使数组只有一个元素发生变化,React 也会执行 effect。

如果想执行只运行一次的 effect(仅在组件挂载和卸载时执行),可以传递一个空数组([])作为第二个参数。

effect 的执行时机

与 componentDidMountcomponentDidUpdate 不同的是,传给 useEffect 的函数会在浏览器完成布局与绘制之后,在一个延迟事件中被调用。这使得它适用于许多常见的副作用场景,比如设置订阅和事件处理等情况,因为绝大多数操作不应阻塞浏览器对屏幕的更新。

然而,并非所有 effect 都可以被延迟执行。例如,一个对用户可见的 DOM 变更就必须在浏览器执行下一次绘制前被同步执行,这样用户才不会感觉到视觉上的不一致。(概念上类似于被动监听事件和主动监听事件的区别。)React 为此提供了一个额外的 useLayoutEffect Hook 来处理这类 effect。它和 useEffect 的结构相同,区别只是调用时机不同。

虽然 useEffect 会在浏览器绘制后延迟执行,但会保证在任何新的渲染前执行。在开始新的更新前,React 总会先清除上一轮渲染的 effect。

useContext 

复用一段上下文、文本

useReducer

接收参数:一个形如 (state, action) => newState 的 reducer、和state的初始值

返回数组:当前的 state 以及与其配套的 dispatch 方法 

useCallback

接收参数:内联回调函数、依赖项数组(回调函数依赖的变量组成的数组);

返回:该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。

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

useRef

返回一个可变的 ref 对象

将 useRef 对象以 <div ref={myRef} /> 形式传入组件,React 都会将 useRef 对象的 .current 属性设置为相应的 DOM 节点(当前组件)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值