useMemo和useCallback的区别

199 阅读2分钟

useCallback和useMemo都是性能优化的手段,类似于类组件中的 shouldComponentUpdate,在子组件中使用 shouldComponentUpdate, 判定该组件的 props 和 state 是否有变化,从而避免每次父组件render时都去重新渲染子组件。发生在渲染之前。 useEffect是发生在组件渲染之后的。

useMemo

useMemo的使用场景。当依赖的数据发生变化的时候,返回的是数据,用在子组件。避免不必要的函数执行。

export default function Father(){
  const [name,setName] = useState("name");
  const [context,setContext] = useState("context")

  return (
    <div>
      <button onClick={()=>{setName(name+"e")}}>name</button>
      <button onClick={()=>{setContext(context+"t")}}>context</button>
      <Son name={name}>{context}</Son>
    </div>
  )
}

export default function Son(props){

  const changeName = () => {
    console.log("执行changeName")
    return props.name + "修改名称" 
  }

// 不使用useMemo,那么只要props变化了,就会执行(点击父组件修改name和context都会执行)
const otherName = changeName()


// 使用useMemo,那么该函数只会在props.name修改的时候执行(点击父组件修改name的时候才会执行)
const otherName = useMemo(()=>changeName(),[props.name])

  return (
    <div>
     <div>{props.children}</div>
      <div>{otherName}</div>
    </div>
  )
}

useCallback

useCallback的使用场景。当依赖的数据发生变化的时候,返回的是函数,用在父组件。避免因为不会变化的函数引起组件刷新。

export default function Father(){
  const [name,setName] = useState("name");
  const [change,setChange] = useState("change")

  const changeFunction = () => { 
     console.log("changeFunction")
  }

  // 不使用useCallback,那么点击修改change,那么子组件就会不断打印“刷新子组件”,但是我们使用了React.memo,所以不是因为change值的改变引起子组件的刷新
  // 真正的原因是函数式组件每次重新渲染,函数组件都会从头执行,这样就会导致我们给子组件绑定的函数其实是已经改变的了
  const otherChangeFunction = changeFunction

  // 使用useCallback,只会在依赖项发生修改的时候,才会执行。使用这个方法,现在修改change就不会导致子组件刷新
  const otherChangeFunction = useCallback(()=> changeFunction,[])

  return (
    <div>
      <button onClick={()=>{setName(name+"e")}}>name</button>
      <button onClick={()=>{setChange(change+"e")}}>change</button>
      <Son name={name} onClick={otherChangeFunction}></Son>
    </div>
  )
}

function Son(props){

  console.log("刷新子组件")

  return (
    <div>
      <div>{props.name}</div>
    </div>
  )
}

export default React.memo(Son)