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

React Native Reanimated 3:父组件卸载时如何阻止子视图退出动画

解决方案

1. 动态控制退出动画的启用

给子组件传入父组件的显示状态,仅在卡片需要保留时启用exiting动画;当父组件触发卸载时,直接禁用退出动画,让组件立即卸载。

修改子组件:

const CardWithText = ({ isVisible }) => {
  const [shownText, setShownText] = useState('text1')
  const currentTimeout = useRef(0)
  
  useEffect(() => {
    if(!currentTimeout.current){
      toggleText();
    }
    return () => clearTimeout(currentTimeout.current) // 清理定时器防止内存泄漏
  },[])

  const toggleText = () => {
    setShownText(prev => prev === "text1" ? "text2" : "text1")
    currentTimeout.current = setTimeout(() => toggleText(), 2500)
  }

  return (
    <View>
      <Animated.Text 
        entering={FadeIn.duration(600).delay(1500)} 
        // 仅在卡片可见时启用退出动画,卸载时直接禁用
        exiting={isVisible ? FadeOut.duration(600).delay(1200) : undefined} 
        key={"card-info-" + shownText}
      >
        {shownText}
      </Animated.Text>
    </View>
  )
}

父组件调用时传入状态:

{ showSection1 ? 
  <CardWithText isVisible={showSection1}/> :
  <SomeOtherComponent/>
}

2. 卸载时清理定时器并强制隐藏文本

在子组件的卸载钩子中清理切换文本的定时器,同时通过状态立即隐藏文本组件,避免触发退出动画。

修改子组件:

const CardWithText = () => {
  const [shownText, setShownText] = useState('text1')
  const currentTimeout = useRef(0)
  
  useEffect(() => {
    toggleText();
    return () => {
      clearTimeout(currentTimeout.current)
      // 立即清空文本状态,让组件直接卸载
      setShownText(null)
    }
  },[])

  const toggleText = () => {
    setShownText(prev => prev === "text1" ? "text2" : "text1")
    currentTimeout.current = setTimeout(() => toggleText(), 2500)
  }

  return (
    <View>
      {/* 只有文本存在时才渲染组件 */}
      {shownText && (
        <Animated.Text 
          entering={FadeIn.duration(600).delay(1500)} 
          exiting={FadeOut.duration(600).delay(1200)} 
          key={"card-info-" + shownText}
        >
          {shownText}
        </Animated.Text>
      )}
    </View>
  )
}

3. 改用手动控制的动画替代组件级entering/exiting

放弃Reanimated的组件级动画API,改用useAnimatedStyle手动控制透明度,这样可以在父组件卸载时直接将透明度设为0且不播放动画,实现立即卸载。

示例:

import { useAnimatedStyle, withTiming } from 'react-native-reanimated'

const CardWithText = ({ isVisible }) => {
  const [shownText, setShownText] = useState('text1')
  const currentTimeout = useRef(0)

  // 手动控制透明度动画
  const textStyle = useAnimatedStyle(() => {
    return {
      opacity: isVisible 
        ? withTiming(1, { duration: 600, delay: 1500 }) // 初始淡入动画
        : withTiming(0, { duration: 0 }) // 卸载时立即透明
    }
  }, [isVisible])

  useEffect(() => {
    if (isVisible) {
      toggleText();
    } else {
      clearTimeout(currentTimeout.current)
    }
    return () => clearTimeout(currentTimeout.current)
  }, [isVisible])

  const toggleText = () => {
    setShownText(prev => prev === "text1" ? "text2" : "text1")
    currentTimeout.current = setTimeout(() => toggleText(), 2500)
  }

  return (
    <View>
      <Animated.Text style={textStyle}>{shownText}</Animated.Text>
    </View>
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:30:38