react 进阶hook 之 useCallback hook

简介: 原因就是在于那个回调函数,还记得属性传入一个函数,如果是直接在事件后面绑定那么每一次render的时候就会重新生成一个函数。并且每一次的函数的地址都不一样,所以这就是为啥 父组件渲染,子组件也会跟着渲染的根本原因。

callback 相信大家都不陌生——回调函数 ,但是 callback hooks 的作用是啥呢?用于得到一个固定引用值的函数,通常用它进行性能优化


语法


const func = useCallback(fn, deps)


  • 参数 fn: 一个函数,需要保存的函数引用


  • 参数 deps: 一个数组,保存函数里面的依赖,如果依赖变化,那么函数的引用地址就会发生变化,否则不执行,这个的用法有点和 effect hooks 类似


案例


有这么一个场景,我们在一个函数组件中,引用了一个类组件(纯组件,数据发生变化才会执行rendrer,),然后在函数组件中做以下事情


。类组件传递数据不改变

。函数组件数据可以自己改变


代码如下:


import React, { PureComponent, useState } from 'react'
interface ITestClassCompP {
  // 数字
  count: number,
  // 点击更改数据
  onClick: () => void
}
// 这是一个存组件,只有props 或者state 变化的时候才会render
class TestClassComp extends PureComponent<ITestClassCompP> {
  render() {
    console.log('TestClassComp 组件渲染了');
    return (
      <div>
        <h1>我是类组件,数据从函数组件穿过来,值是  {this.props.count}</h1>
        <button onClick={this.props.onClick}> + 1 </button>
      </div>
    )
  }
}
// 测试组件
export function TestCallbackHook() {
  // 状态值
  const [count, setCount] = useState(0)
  console.log('TestCallbackHook 组件渲染了');
// 输入框的值
  const [inputVal, setInputVal] = useState(0)
  return (
    <>
      <TestClassComp
        count={count}
        onClick={() => {
          setCount(count + 1)
        }} />
      <input
        value={inputVal}
        type="number"
        onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
          setInputVal(parseInt(e.target.value))
        }} />
    </>
  )
}


效果


20210408095154538.gif


从代码中,我们可以知道,我们点击+ 1 按钮的时候,两个组件需要渲染,但是输入框的数据改变是不应该渲染子组件的,因为我们的count 数据是没有变化的,这是为啥呢?


原因就是在于那个回调函数,还记得属性传入一个函数,如果是直接在事件后面绑定那么每一次render的时候就会重新生成一个函数。并且每一次的函数的地址都不一样,所以这就是为啥 父组件渲染,子组件也会跟着渲染的根本原因。


如何解决


还记得类组件是如何解决这个问题么? 在类组件中,我们的事件绑定函数定义是直接使用 esnext 的语法,定义出来,这样就不会导致每一次的函数引用地址不变了,那么在函数组件可以使用么?


答案是: 不行,有兴趣的自己去尝试


20210408100423656.png


使用 callback hooks 来保存引用


改造函数,如下


20210408100603907.png


最终效果


20210408100936975.gif


这个效果才是我们想要的!

相关文章
|
8月前
|
前端开发
React中useEffect、useCallBack、useLayoutEffect
React中useEffect、useCallBack、useLayoutEffect
|
4月前
|
缓存 前端开发
React中函数式Hooks之memo、useCallback的使用以及useMemo、useCallback的区别
React中的`memo`是高阶组件,类似于类组件的`PureComponent`,用于避免不必要的渲染。`useCallback` Hook 用于缓存函数,避免在每次渲染时都创建新的函数实例。`memo`可以接收一个比较函数作为第二个参数,以确定是否需要重新渲染组件。`useMemo`用于缓存计算结果,避免重复计算。两者都可以用来优化性能,但适用场景不同:`memo`用于组件,`useMemo`和`useCallback`用于值和函数的缓存。
114 1
|
5月前
|
前端开发
React 中的 Hook 概念
【8月更文挑战第31天】
46 0
|
6月前
|
前端开发
React useImperativeHandle Hook
【7月更文挑战第1天】React useImperativeHandle Hook
36 3
|
6月前
|
前端开发 JavaScript 数据格式
react18【系列实用教程】Hooks (useState,useReducer,useRef,useEffect,useContext,useMemo,useCallback,自定义 Hook )
react18【系列实用教程】Hooks (useState,useReducer,useRef,useEffect,useContext,useMemo,useCallback,自定义 Hook )
125 1
|
6月前
|
存储 前端开发 JavaScript
react hooks 学习进阶
【7月更文挑战第12天】 React Hooks(自16.8版起)让函数组件能处理状态和副作用。useState用于添加状态管理,useEffect处理副作用,useContext共享数据,useReducer处理复杂状态逻辑,useRef获取引用。进阶技巧涉及性能优化,如useMemo和useCallback,以及遵循规则避免在不适当位置调用Hooks。理解异步更新机制和结合Redux等库提升应用复杂性管理。持续学习新技巧是关键。
68 0
|
6月前
|
前端开发
Vue3 【仿 react 的 hook】封装 useTitle
Vue3 【仿 react 的 hook】封装 useTitle
66 0
|
6月前
|
前端开发 API
Vue3 【仿 react 的 hook】封装 useLocation
Vue3 【仿 react 的 hook】封装 useLocation
50 0
|
6月前
|
前端开发
react18【系列实用教程】Hooks 闭包陷阱 (2024最新版)含useState 闭包陷阱,useEffect 闭包陷阱,useCallback 闭包陷阱
react18【系列实用教程】Hooks 闭包陷阱 (2024最新版)含useState 闭包陷阱,useEffect 闭包陷阱,useCallback 闭包陷阱
86 0
|
6月前
|
缓存
react18【系列实用教程】useCallback —— 缓存函数 (2024最新版)
react18【系列实用教程】useCallback —— 缓存函数 (2024最新版)
61 0