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"
}
相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大3 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师3 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学3 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端