ReactHooks专题-useCallback

useCallBack的使用

useCallback在什么时候使用?
场景:将一个组件中的函数,传递给子组件进行回调使用的时候,使用useCallback对函数进行处理

useCallBack实际的目的是为了进行性能优化;
如何进行性能优化呢?(基本上都配合memo使用)

memo基本使用

问题再现

react中当组件的props或者state变化时,会重新渲染视图,实际开发中会遇到不必要渲染的场景

子组件

function ChildComp () {
  console.log('render child-comp ...')
  return <div>Child Comp ...</div>
}

父组件

function ParentComp () {
  const [ count, setCount ] = useState(0)
  const increment = () => setCount(count + 1)

  return (
    <div>
      <button onClick={increment}>点击次数:{count}</button>
      <ChildComp />
    </div>
  );
}

当子组件(初次)重新载入,会打印console.log语句
点击父组件中的button组件,会修改count的值,进而导致整个父组件都会重新渲染,此时子组件理论上来说并不需要重新渲染,因为它并没有依赖任何父组件的值,但是现在它重新渲染了;
我们期待的结果:子组件的propsstate没有发生变化的时候,即使父组件重新渲染,也不要重新渲染子组件;

解决问题

修改子组件,用 React.memo() 包一层。

import React, { memo } from 'react'

const ChildComp = memo(function () {
  console.log('render child-comp ...')
  return <div>Child Comp ...</div>
})

useCallback配合memo使用

问题再现

上面的例子中,父组件只是简单的调用了子组件,并没有给子组件传递如任何的属性;如果给子组件传递了一些属性
子组件

import React, { memo } from 'react'

const ChildComp = memo(function ({ name, changeName}) {
  console.log('render child-comp ...')
  return <>
    <div>Child Comp ... {name}</div>
    <button onClick={() => changeName('hello')}>改变 name 值</button>
  </>
})

父组件

function ParentComp () {
  const [ count, setCount ] = useState(0)
  const [ name, setName ] = useState('张三')
  const changeName = (newName) => setName(newName)

  return (
    <div>
      <button onClick={()=>{
      	setCount(count + 1)
      }}>点击次数:{count}</button>
      <ChildComp name={name} changeName={changeName}/>
    </div>
  );
}

当父组件的按钮发生了点击之后,子组件即使是在用memo包裹的情况下,依然会重新打印;
但是这是为什么呢?

  • 父组件按钮点击,导致父组件重新渲染,那么父组件中定义的changeName函数也会重新渲染;换句话说,父组件中两次渲染定义的changeName函数并不是同一个函数,那么就导致了,传入子组件中的changeName函数也发生了变化,子组件监听到了props的改变所以才会重新渲染;

解决问题

父组件

function ParentComp () {
  const [ count, setCount ] = useState(0)
  const [ name, setName ] = useState('张三')
  const changeName = useCallback((newName) => {
  	setName(newName)
  },[])

  return (
    <div>
      <button onClick={()=>{
      	setCount(count + 1)
      }}>点击次数:{count}</button>
      <ChildComp name={name} changeName={changeName}/>
    </div>
  );
}

此时点击父组件按钮,控制台不会打印子组件被渲染的信息了。
究其原因:useCallback() 起到了缓存的作用,即便父组件渲染了,useCallback() 包裹的函数也不会重新生成,会返回上一次的函数引用。

你可能感兴趣的:(react,Hooks,react.js,javascript,前端)