You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中使用framer-motion时,如何避免MotionComponent不必要重渲染?

避免React组件中动画组件的不必要重渲染

原问题代码

const App = () => {

  // state here
  const [state,setState] = useState([]);

  const handleClick = (item) => {
       setState(prev=> [...prev, item]); // 修正原代码语法错误
  }

  return (
    <>
     <MotionComponent/> // 执行重复动画的组件
     <StateComponent handleClick={handleClick}/> // 点击更新state,触发App重渲染导致MotionComponent也重渲染
    </>
  )
}

问题:StateComponent的点击事件更新App组件的state时,会导致App重渲染,进而让不依赖任何state/props的MotionComponent也跟着重渲染,打断或重复触发动画,如何避免?


解决方案

1. 用React.memo包裹MotionComponent

React.memo是高阶组件,会对组件的props做浅比较,若props无变化则跳过重渲染。由于MotionComponent未接收任何props,App重渲染时它不会跟着更新。

修改后代码:

import { memo } from 'react';

// 用memo包裹动画组件
const MemoizedMotionComponent = memo(MotionComponent);

const App = () => {
  const [state,setState] = useState([]);

  const handleClick = (item) => {
       setState(prev=> [...prev, item]);
  }

  return (
    <>
     <MemoizedMotionComponent/>
     <StateComponent handleClick={handleClick}/>
    </>
  )
}

2. 将MotionComponent提取到App组件外部

如果MotionComponent不需要访问App内部的state、props或上下文,可将其移到App组件外部。此时App的重渲染不会影响它,因为它不在App的渲染范围内。

修改后代码:

// 把动画组件放在App外部
const MotionComponent = () => {
  // 动画逻辑
  return <div>重复动画内容</div>;
};

const App = () => {
  const [state,setState] = useState([]);

  const handleClick = (item) => {
       setState(prev=> [...prev, item]);
  }

  return (
    <>
     <MotionComponent/>
     <StateComponent handleClick={handleClick}/>
    </>
  )
}

3. 优化handleClick函数(附带优化StateComponent的重渲染)

虽然核心问题是MotionComponent,但StateComponent也可能因handleClick的引用变化而重渲染。用useCallback缓存函数引用,结合React.memo包裹StateComponent,可进一步优化整体性能。

修改后代码:

import { memo, useCallback } from 'react';

const MemoizedMotionComponent = memo(MotionComponent);
const MemoizedStateComponent = memo(StateComponent);

const App = () => {
  const [state,setState] = useState([]);

  // 用useCallback缓存handleClick,依赖项为空因为setState是稳定引用
  const handleClick = useCallback((item) => {
       setState(prev=> [...prev, item]);
  }, []);

  return (
    <>
     <MemoizedMotionComponent/>
     <MemoizedStateComponent handleClick={handleClick}/>
    </>
  )
}

内容的提问来源于stack exchange,提问作者LittleTeemo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 22:17:15