• React Hooks系列之useCallback


    useCallback介绍

    useCallback 可以说是 useMemo 的语法糖,能用 useCallback 实现,都可以用 useMemo,常用语 react 的性能优化。 在 react 中我们经常面临一个子组件渲染优化的问题,尤其是在向子组件传递函数 props 时,每次 render 都会创建新函数,导致子组件不必要的渲染,浪费性能,这个时候,就是useCallback 的用武之地,useCallback 可以保证,无论 render 多少次,我们的函数都是同一个函数,减少了不断创建的开销。

    const memoCallback = useCallback(callback, array)
    

    返回一个memoized 回调函数。

    • callback 是一个函数用于处理逻辑
    • array 控制 useCallback 重新执行的数组,array 改变时才会重新执行useCallback
    1. 数组,每次更新都会重新计算
    2. 空数组,只会计算一次
    3. 依赖对应的值,对应的值发生变化重新计算
    • useCallback(fn, deps) 相当于 useMemo(() => fn, deps)

    useCallback 使用

    function App () {
      const [ count, setCount ] = useState(0)
      const add = useCallback(() => count + 1, [count])
      return (
        <div>
          点击次数: { count }
          <br/>
          次数加一: { add() }
          <button onClick={() => { setCount(count + 1)}}>点我</button>
        </div>
        )
    }
    

    应用场景:

    import React, { useState } from 'react'
    class Test extends React.PureComponent {
      render() {
        console.log("Test Render")
        return <div>
          <h1>{this.props.text}</h1>
          <button onClick={this.props.onClick}>改变文本</button>
        </div>
      }
    }
    const Parent = () => {
      console.log("Parent Render")
      const [txt, setTxt] = useState(123)
      const [n, setN] = useState(0)
      return (
        <div>
          <Test text={txt} onClick={() => {
            setTxt(123)
          }}></Test>
          <input type="number"
            value={n}
            onChange={
              e => {
                setN(parseInt(e.target.value))
              }
            }></input>
        </div>
      )
    }
    const App = () => {
      return (
        <div>
          <Parent />
        </div>
      )
    }
    export default App
    
    

    理论来说,Test 作为纯组件,只有在传入发生改变的时候才会重新渲染,当点击改变文本的按钮时,setTxt所更改的值与本身Txt的值相同,所以Test 组件不会重新渲染,不会打印test Render

    问题所在就是,当Parent 组件中的其他值发生改变的时候,Parent 组件便会重新渲染,而Test 组件中Txt 的值虽然没有改变, 但传入的() => { setTxt(123) } 作为方法对象,会创建一个新的地址栈, 两次地址的指向不同了,所以会认为传入的值发生了改变,所以 Test 组件发生了重新渲染

    image

    这样的渲染浪费了不必要的性能,所以 useCallback 就是用来解决这一问题的

    import React, { useState,useCallback } from 'react'
    class Test extends React.PureComponent {
      render() {
        console.log("Test Render")
        return <div>
          <h1>{this.props.text}</h1>
          <button onClick={this.props.onClick}>改变文本</button>
        </div>
      }
    }
    const Parent = () => {
      console.log("Parent Render")
      const [txt, setTxt] = useState(123)
      const [n, setN] = useState(0)
      const hhh = useCallback(()=> {
        setTxt(223)
      },[])
      return (
        <div>
          <Test text={txt} onClick={hhh}></Test>
          <input type="number"
            value={n}
            onChange={
              e => {
                setN(parseInt(e.target.value))
              }
            }></input>
        </div>
      )
    }
    const App = () => {
      return (
        <div>
          <Parent />
        </div>
      )
    }
    export default App
    
    

    image

    这样当改变n的值时 Test 组件就不会跟着渲染啦

  • 相关阅读:
    .Net中获取打印机的相关信息
    如何在windows server 2008上配置NLB群集
    jvm分析内存泄露
    JVM调优
    线程池工作队列饱和策略
    线程池的处理流程:
    Java的Executor框架和线程池实现原理(转)
    线程池实现原理详解:
    futer.get()(如果任务没执行完将等待)
    sql注入
  • 原文地址:https://www.cnblogs.com/tommymarc/p/16160418.html
Copyright © 2020-2023  润新知