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

React Animated值超过0.8时触发函数 如何规避旧状态监听器残留问题

问题原因

你的useEffect仅在依赖变更时新增监听器,没有移除上一轮渲染生成的旧监听器:

  • 每次DATA_LAYER.names更新都会注册一个新的监听函数,旧监听函数因为闭包特性,绑定的是当时的DATA_LAYER.names快照
  • 多个监听器同时触发时,只要有一个旧监听器绑定的names是非空状态,就会触发不符合预期的跳转逻辑

修复方案

给useEffect添加清理逻辑,每次重新注册监听器前,先移除上一轮的旧监听器:

const DATA_LAYER = React.useContext(DataLayerContext);
const reactAnimated = React.useRef(new Animated.Value(0)).current;
/*
  Some simple functions to move the reactAnimated value
*/
const moveNow = () =>{
    if (DATA_LAYER.names.length!==0){
      props.navigation.navigate("loadingscreen");
    }
}

React.useEffect(()=>{
    // 注册监听器,获取监听器唯一ID
    const listenerId = reactAnimated.addListener(val=>{
       if (val.value > .8){
          moveNow() // move to next page
       }
    });
    // 返回清理函数,依赖变更/组件卸载时自动移除当前监听器
    return () => {
      reactAnimated.removeListener(listenerId);
    }
},[DATA_LAYER.names])

可选优化方案(减少监听器重复注册)

如果不需要每次names变更都重新生成监听逻辑,也可以用ref存储最新的names状态,只需要在组件挂载时注册一次监听器即可,避免反复增删监听的性能损耗:

const DATA_LAYER = React.useContext(DataLayerContext);
const reactAnimated = React.useRef(new Animated.Value(0)).current;
// 用ref同步最新的names状态,避免闭包捕获旧值
const latestNamesRef = React.useRef(DATA_LAYER.names);

// 同步更新ref存储的names
React.useEffect(()=>{
  latestNamesRef.current = DATA_LAYER.names;
}, [DATA_LAYER.names]);

const moveNow = () =>{
    if (latestNamesRef.current.length!==0){
      props.navigation.navigate("loadingscreen");
    }
}

// 仅在组件挂载时注册一次监听器
React.useEffect(()=>{
    const listenerId = reactAnimated.addListener(val=>{
       if (val.value > .8){
          moveNow()
       }
    });
    return () => reactAnimated.removeListener(listenerId);
},[])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 20:45:07