react useCallback应用

函数组件

函数组件

函数组件实际上就是一个函数,接收props对象参数,返回一个React元素。

js 复制代码
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

函数组件重新渲染

React 组件在组件的状态 state 或者组件的属性 props 改变的时候,会重新渲染。函数组件重新渲染时,会重新执行这个组件函数。

useCallback用法

js 复制代码
let memoizedCallback = useCallback(fn, dependencies)

参数

fn:

想要缓存的函数。在初次调用(初次渲染)时,返回函数fn。下一次调用(下一次渲染)时,如果依赖项没有变化,返回上次的函数fn;如果依赖项发生了变化,返回最新的函数fn'。
dependencies:

是否更新fn的依赖列表。响应式值包括 props、state,和所有在你组件内部直接声明的变量和函数。

返回值

在初次渲染时,useCallback 返回你已经传入的 fn 。

在之后的渲染中, 如果依赖没有改变,useCallback 返回上一次渲染中缓存的 fn 函数;否则返回这一次渲染传入的 fn。

场景

减少子组件重新渲染

当父组件重新渲染时,子组件也会重新渲染,这样造成不必要的开销。React.memo解决了这个问题。React.memo会浅比较当前组件的props与上一次渲染时的 props。如果props没有变化,跳过重新渲染。

当父组件的函数通过props传递给子组件时,使用useCalback包裹函数,配合React.memo防止子组件重新渲染。

js 复制代码
// 子组件使用 React.memo 优化
const ChildComponent = React.memo(function ChildComponent({ onClick }) {
  console.log("ChildComponent rendered");
  return <button onClick={onClick}>Click me</button>;
});

// 父组件使用 useCallback
function ParentComponent() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState("");

  // 使用 useCallback 记忆回调函数
  const handleClick = useCallback(() => {
    setCount(c => c + 1);
  }, []); // 空依赖数组,因为不依赖任何值

  return (
    <div>
      <input value={text} onChange={e => setText(e.target.value)} />
      <p>Count: {count}</p>
      <ChildComponent onClick={handleClick} />
    </div>
  );
}

防止频繁触发useEffect

如下代码,父组件的函数handleChange函数传递给子组件。当在子组件中的useEffect hook中调调用父组件handleChange函数时,会导致无限循环渲染父子组件。

子组件useEffect中调用handleChange函数后,执行这个函数。函数中有语句setState,触发父组件重新渲染。父组件重新渲染,在重新渲染时创建新的handleChange函数。
handleChange函数改变了,则又会执行useEffect里面的handleChange函数。这样造成了无限循环调用。

js 复制代码
function Parent(){
  const [state, setState] = useState()
  
  function handleChange(input){
    setState(...)
  }

  return <Child onChange={handleChange} />
}

function Child({onChange}){
  const [state, setState] = useState()
  
  useEffect(()=>{
    onChange(...)
  },[onChange])

  return "Child"
}

下面使用useCallback解决这一问题。给父组件的handleChange函数使用useCallback包裹。

js 复制代码
function Parent(){
  const [state, setState] = useState()
  
  let handleChange = useCallback((input) => {
    setState(...)
  },[])

  return <Child onChange={handleChange} />
}

function Child({onChange}){
  const [state, setState] = useState()
  
  useEffect(()=>{
    onChange(...)
  },[onChange])

  return "Child"
}
相关推荐
lovingsoft6 分钟前
Chrome Lighthouse 详解
前端·chrome
Qlly16 分钟前
全栈工程师怎么接需求?从一句「加个功能」聊到能开发、能验收
前端·后端
马可家的菠萝20 分钟前
你的微信“文件传输助手”,是不是已经成了第二个网盘?
前端·后端·架构
略略略啦21 分钟前
Vibe Coding 基于Spec DD和TDD的实践指南
前端
shmily麻瓜小菜鸡42 分钟前
前端实现图片与PDF文字识别敏感信息打码方案
前端·pdf·状态模式
打工仔折腾 AI1 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
汉堡大王95271 小时前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端
看浪的路人1 小时前
第9讲:大模型应用监控与可观测性——OpenTelemetry + Prometheus + Grafana 全链路追踪
java·前端·spring
内存过载1 小时前
用表格模拟甘特图:项目排期的土办法
前端·低代码
葡萄城技术团队1 小时前
用 SpreadJS 数据验证实现省市区三级联动
前端