# react-useCallback

2 min read
Table of Contents

主要作用

核心概念

注意事项

示例代码

child1
John
20
child2
John
20
import React, { useCallback, useState } from 'react'

interface Props {
  callback: () => void
  user: {
    name: string
    age: number
  }
  text: string
}

const Child1 = React.memo((props: Props) => {
  console.log('Child1 rendered')
  return (
    <div className="border border-[#2b2b2b] flex items-center justify-between p-4">
      <div className="flex items-center justify-start gap-4">
        <div>{props.text}</div>
        <div>{props.user.name}</div>
        <div>{props.user.age}</div>
      </div>
      <button onClick={props.callback}>callback</button>
    </div>
  )
})
const Child2 = React.memo((props: Props) => {
  console.log('Child2 rendered')
  return (
    <div className="border border-[#2b2b2b] flex items-center justify-between p-4">
      <div className="flex items-center justify-start gap-4">
        <div>{props.text}</div>
        <div>{props.user.name}</div>
        <div>{props.user.age}</div>
      </div>
      <button onClick={props.callback}>callback</button>
    </div>
  )
})

export default function Parent() {
  const [input, setInput] = useState('')
  const [user, setUser] = useState({
    name: 'John',
    age: 20,
  })
  const callback = () => {
    console.log('callback')
  }
  const callback2 = useCallback(callback, [user])
  /**
   * 这里触发onChange事件会导致父组件重新渲染
   * 导致callback函数重新创建(useCallback虽然内容没变,但是引用即内存地址变了)
   * 导致Child1子组件重新渲染
   * 所以会不断触发子组件的初始化打印
   * 但是Child2子组件由于使用的useCallback缓存了callback函数
   * 所以只有user改变的时候才会改变
   */
  return (
    <>
      <input
        type="text"
        value={input}
        onChange={(e) => setInput(e.target.value)}
        className="mb-4 mr-4"
      />
      <button
        onClick={() =>
          setUser({
            ...user,
            name: input,
          })
        }
      >
        设置username
      </button>
      <Child1 callback={callback} user={user} text="child1" />
      <Child2 callback={callback2} user={user} text="child2" />
    </>
  )
}
My avatar

Thanks for reading my blog post! Feel free to check out my other posts or contact me via the social links in the footer.


More Posts

Comments