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

react-spring的useSpring的onRest回调搭配react-flip-toolkit不触发如何解决

问题核心原因

1. 组件提前卸载

你当前的实现逻辑中,searchResults 是根据 searchQuery 直接过滤得到的数组,当搜索关键词变化时,不符合条件的项会直接从渲染列表中移除,对应的 Card 组件会立刻被React卸载。此时 onExit 回调刚触发,你调用 api.start 启动的退出动画还未执行完成,动画实例就随组件销毁了,自然不会触发 onRest 回调。

2. 依赖版本兼容性问题

你使用的 react-spring@9.1.2 属于v9早期版本,存在多个已知的 onRest 回调不触发的bug,且该版本和 Gatsby@3.4.0 的SSR渲染逻辑存在兼容性问题,也可能导致回调失效。


解决方案

第一步:修复列表渲染逻辑

不要直接过滤掉要删除的项,给数据项加删除标记,等退出动画完成后再真正移除数据:

const Container = () => {
  const [searchQuery, setSearchQuery] = useState('');
  // 原始全量数据
  const [allItems, setAllItems] = useState([]);
  // 带状态的渲染列表,保留待删除项直到动画结束
  const [renderItems, setRenderItems] = useState([]);

  // 搜索时只打删除标记,不直接移除
  useEffect(() => {
    const filtered = allItems.filter(item => 
      item.title.includes(searchQuery)
    ).map(item => ({...item, isDeleted: false}));
    // 找出将要删除的项,标记为删除状态
    const toDelete = renderItems.filter(item => 
      !filtered.find(f => f.id === item.id)
    ).map(item => ({...item, isDeleted: true}));
    setRenderItems([...filtered, ...toDelete]);
  }, [searchQuery, allItems]);

  // 真正移除已经完成退出动画的项
  const handleRemoveItem = (id) => {
    setRenderItems(prev => prev.filter(item => item.id !== id))
  }

  return (
    <Flipper
      flipKey={searchQuery}
      decisionData={searchQuery}
      className="row"
    >
      {renderItems.map((item) => (
        <Card
          key={item.id}
          item={item}
          onRemove={handleRemoveItem}
        />
       ))}
    </Flipper>
  );
}

第二步:修改Card组件逻辑,动画完成后调用移除方法

const Card = ({ item, onRemove }) => {
  const [spring, api] = useSpring(() => ({
    opacity: 1,
    transform: 'scale(1)',
  }));

  const onExit = (el, index, removeElement) => {
    api.start({
      opacity: 0,
      transform: 'scale(0.9)',
      onRest: () => {
        // 动画完成后真正移除元素
        onRemove(item.id)
        removeElement()
      },
  });

  return (
    <Flipped
      flipId={item.vizcartPath}
      stagger
      onExit={onExit}
    >
      <animated.div className="col-6 col-md-4 col-xl-3 p-5 card-container" style={spring}>
        TEST
      </animated.div>
    </Flipped>
  );
};

第三步:修复依赖兼容问题

将 react-spring 升级到9.5.0及以上版本,该版本修复了大量v9早期版本的回调bug,和Gatsby 3.x的兼容性更好:

npm install react-spring@latest
# 或者用yarn
yarn add react-spring@latest

升级后删除项目根目录的 node_modules 文件夹和 package-lock.json/yarn.lock 文件,重新安装依赖即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 04:45:10