RN 中的 useRef 再说明

useRef 是什么

useRef(initialValue) 返回一个 在组件整个生命周期内保持不变的对象{ current: initialValue }
更新 ref.current 不会触发重新渲染,这点和 useState 不同。


你代码里的两种用法

1. useRef(new Animated.Value(0)).currentpage/index.js 第 92 行)

    const lineAnimateRef = useRef(new Animated.Value(0)).current

    const onPress = (tab, index) => {
        componentState.setTopTabberIndex(index)
    }

    useEffect(() => {

        Animated.spring(lineAnimateRef, {
            toValue: topTabberIndex * UIConfig.rpxToPx(100 + 96),
            bounciness: 0,
            useNativeDriver: true
        }).start()

这里在 第一次渲染 时执行 useRef(new Animated.Value(0)),得到 { current: AnimatedValue },再取 .current,所以变量 lineAnimateRef 实际指向的是 Animated.Value 实例本身,不是「整颗 ref 对象」。

目的:保证 Animated.Value 只创建一次(不会在每次渲染时 new),同时变量名可以直接当动画值传给 Animated.spring
若写成 const r = useRef(new Animated.Value(0)),就要用 r.current 传给 Animated.spring,语义等价。

2. useRef(null) + 传给 refHome/index.js 第 54–64 行)

const ScrollViewWithTopTabber = observer(({ navigation }) => {
    const componentState = useComponentState()
    const scrollRef = useRef(null)

    useEffect(() => {
        scrollRef.current.scrollTo({ x: componentState.topTabberIndex * UIConfig.width, animated: true })
    }, [componentState.topTabberIndex])



    return (
        <ScrollView
            ref={scrollRef}

这里 useRef(null) 保留整颗 refscrollRef.current 先是 null,挂载后由 React 填成 ScrollView 实例,用于在 useEffect命令式调用 scrollTo


常见场景归纳

场景 典型形式 说明
引用 DOM / 原生组件实例 useRef(null) + <ScrollView ref={scrollRef} /> focusscrollTomeasure 等命令式 API
保存可变值且不重渲染 const count = useRef(0)count.current++ 存定时器 id、上一次 props、渲染次数等
保存只创建一次的对象 useRef(expensive()).currentuseRef(new Animated.Value(0)).current 避免每次 render 重新创建;动画值、第三方实例常用
子组件暴露方法(可选) useImperativeHandle + forwardRef 父组件通过 ref 调子组件方法
与类组件对比 函数组件里用 useRef 替代实例字段 this.xxx

示例代码

① 组件实例 ref(与你 Home 一致)

const scrollRef = useRef(null);

return <ScrollView ref={scrollRef} />;
// scrollRef.current?.scrollTo(...)

② 不触发渲染的可变数据

const prevId = useRef();
useEffect(() => {
  prevId.current = id;
}, [id]);

③ 只初始化一次的值(与你 Animated.Value 一致)

// 方式 A:常用写法,变量直接是 Animated.Value
const anim = useRef(new Animated.Value(0)).current;

// 方式 B:保留 ref 对象
const animRef = useRef(new Animated.Value(0));
Animated.spring(animRef.current, { ... });

④ 存定时器 / 订阅,卸载时清理

const timerRef = useRef(null);
useEffect(() => {
  timerRef.current = setInterval(...);
  return () => clearInterval(timerRef.current);
}, []);

小结:第一种用 useRef 锁住只创建一次的 Animated.Value(取 .current 只是为了少写一层 xxx.current);第二种用 useRef(null) 接住组件实例,做 命令式滚动。两者都是 useRef「跨渲染保持同一引用、改 current 不触发渲染」的典型用法。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容