首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何使createRef/useRef不以最后一个值为目标。而是去它应该去的地方

在使用React的createRefuseRef时,如果你发现它们总是以最后一个值为目标,而不是它们应该去的地方,这通常是因为你在循环中创建了多个引用,但没有为每个引用分配一个唯一的键或标识符。

基础概念

  • createRef:这是React的一个类组件API,用于创建一个可以在组件的整个生命周期内保持不变的引用。
  • useRef:这是React的一个Hooks API,用于函数组件,功能与createRef类似,但它是基于Hooks的,因此只能在函数组件或自定义Hooks中使用。

问题原因

当你在循环中创建多个引用时,例如在一个列表渲染中,如果没有为每个元素分配一个唯一的键,React可能会复用之前的DOM节点,导致ref指向最后一个元素。

解决方法

使用唯一键

确保在渲染列表时为每个元素分配一个唯一的键。这有助于React正确地识别和更新每个元素。

代码语言:txt
复制
const listItems = items.map((item, index) => (
  <li key={item.id} ref={el => (listItemRefs.current[index] = el)}>
    {item.text}
  </li>
));

在这个例子中,item.id作为唯一键,listItemRefs是一个数组,用于存储每个元素的引用。

使用回调函数

使用回调函数来设置ref,这样可以确保每次渲染时都会调用该函数,从而正确地设置每个元素的引用。

代码语言:txt
复制
const listItems = items.map((item, index) => (
  <li key={item.id} ref={el => (listItemRefs.current[index] = el)}>
    {item.text}
  </li>
));

应用场景

这种技术通常用于需要直接访问DOM元素的场景,例如:

  • 管理焦点(如自动聚焦表单输入)
  • 触发DOM动画
  • 集成第三方DOM库

示例代码

代码语言:txt
复制
import React, { useRef } from 'react';

function ListComponent({ items }) {
  const listItemRefs = useRef([]);

  return (
    <ul>
      {items.map((item, index) => (
        <li key={item.id} ref={el => (listItemRefs.current[index] = el)}>
          {item.text}
        </li>
      ))}
    </ul>
  );
}

export default ListComponent;

参考链接

通过上述方法,你可以确保createRefuseRef指向正确的DOM元素,而不是总是以最后一个值为目标。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

精读《useRef 与 createRef 的区别》

1 引言 useRef 是常用的 API,但还有一个 createRef 的 API,你知道他们的区别吗?...2 概述 其实原文就阐述了这样一个事实:useRef 仅能用在 FunctionComponent,createRef 仅能用在 ClassComponent。...由于 Ref 是贯穿 FunctionComponent 所有渲染周期的实例,理论上在任何地方都可以做修改,比如: function App() { const valueRef = React.useRef...不仅可以拿到组件引用、创建一个 Mutable 副作用对象,还可以配合 useEffect 存储一个较老的值,最常用来拿到 previousProps,React 官方利用 Ref 封装了一个简单的...最后,不要滥用 Ref,Mutable 引用越多,对 React 来说可维护性一般会越差。 4 总结 你还挖掘了 useRef 哪些有意思的使用方式?欢迎在评论区留言。

80910

看完这篇,你也能把 React Hooks 玩出花

,参数为一个固定的值或者一个有返回值的方法。...借助这样的特性,我们要做的就是让目标副作用在初始化执行一次后再也不会被调用,于是只要让与该副作用相关联的状态为空,不管其他状态如何变动,该副作用都不会再次执行,即实现了 componentDidMount...useRef useRef 接受一个参数,为 ref 的初始值。...类似于类组件中的 createRef 方法 ,该钩子会返回一个对象,对象中的 current 字段为我们 指向的实例 / 保存的变量,可以实现获得目标节点实例或保存状态的功能。...useRef 保存的变量不会随着每次数据的变化重新生成,而是保持在我们最后一次赋值时的状态,依靠这种特性,再配合 useCabllback 和 useEffect 我们可以实现 preProps/preState

3.5K31
  • 看完这篇,你也能把 React Hooks 玩出花

    ,参数为一个固定的值或者一个有返回值的方法。...借助这样的特性,我们要做的就是让目标副作用在初始化执行一次后再也不会被调用,于是只要让与该副作用相关联的状态为空,不管其他状态如何变动,该副作用都不会再次执行,即实现了 componentDidMount...useRef useRef 接受一个参数,为 ref 的初始值。...类似于类组件中的 createRef 方法 ,该钩子会返回一个对象,对象中的 current 字段为我们 指向的实例 / 保存的变量,可以实现获得目标节点实例或保存状态的功能。...useRef 保存的变量不会随着每次数据的变化重新生成,而是保持在我们最后一次赋值时的状态,依靠这种特性,再配合 useCabllback 和 useEffect 我们可以实现 preProps/preState

    2.9K20

    从 React 源码彻底搞懂 Ref 的全部 api

    改变 ref 传递的值,使用 useImperativeHandle,第一个参数是 ref,第二个参数是返回 ref 值的函数 相信开发 React 项目,大家或多或少会用到这些 api。...,在代码里的 ref.current 就能拿到这个元素了: 而且我们可以发现,他只是对 ref.current 做了赋值,并不管你是用 createRef 创建的、useRef 创建的,还是自己创建的一个普通对象...我们试验一下: 我创建了一个普通对象,current 属性依然被赋值为 input 元素。 那我们用 createRef、useRef 的意义是啥呢?...看下源码就知道了: createRef 也是创建了一个这样的对象,只不过 Object.seal 了,不能增删属性。 用自己创建的对象其实也没啥问题。 那 useRef 呢?...的回调: 这里就调用了 useImperativeHandle 的回调: 更新了 ref 的值: hook 的 effect 和前面的处理 ref 的 effect 保存在不同的地方: 增删改

    96340

    React Ref 使用总结

    不要在 Hook 组件(或者函数组件)中使用 createRef,它没有 Hook 的功能,函数组件每次重渲染,createRef 就会生成新的 ref 对象。...使用 useRef useRef 除了访问 DOM 节点外,useRef 还可以有别的用处,你可以把它看作类组件中声明的实例属性,属性可以存储一些内容,内容改变不会触发视图更新。...以一个计时器的例子了解 useRef 的用法。 Demo 描述:一个 100ms 的计时器,当点击 Start 按钮时就会计时,点击 End 按钮时停止计时,如何实现?...再看一个例子,实现一个下面动图这样的功能,输入框输入的数字相当于计时器的毫秒延迟,当输入框数值变化时计时器会做相应的调整。如何实现? ?...显然,我们需要两个状态,一个是 count,表示数字的变化;另一个是 delay,延迟时间会随着输入值不不同而变化。

    7K40

    React 原理问题

    以setState为例,在 react 内部,每个组件(Fiber)的 hooks 都是以链表的形式存在memoizeState属性中。...shouldComponentUpdate(nextProps, nextState) 有两个参数nextProps和nextState,表示新的属性和变化之后的state,返回一个布尔值,true表示会触发重新渲染...React 父组件如何调用子组件中的方法?...redux是将整个应用状态存储到一个地方成为store, 里面保存着一个状态树store three, 组件可以派发(dispatch)行为(action)给store, 组件内部通过订阅store中的状态...数据可变性的不同 Redux强调的是对象的不可变性,不能直接操作状态对象。而是在原来状态对象的基础上返回一个新的状态对象,最后返回应用的上一个状态 Mobx可以直接使用新值更新状态对象 4.

    2.5K00

    医疗数字阅片-医学影像-REACT-React.createRef()-Refs and the DOM关于回调 refs 的说明

    注意 下面的例子已经更新为使用在 React 16.3 版本引入的 React.createRef() API。如果你正在使用一个较早版本的 React,我们推荐你使用回调形式的 refs。...const node = this.myRef.current; ref 的值根据节点的类型而有所不同: 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() ...为 DOM 元素添加 ref 以下代码使用 ref 去存储 DOM 节点的引用: class CustomTextInput extends React.Component { constructor...为 class 组件添加 Ref 如果我们想包装上面的 CustomTextInput,来模拟它挂载之后立即被点击的操作,我们可以使用 ref 来获取这个自定义的 input 组件并手动调用它的 focusTextInput...不同于传递 createRef() 创建的 ref 属性,你会传递一个函数。这个函数中接受 React 组件实例或 HTML DOM 元素作为参数,以使它们能在其他地方被存储和访问。

    1.7K30

    百度前端高频react面试题总结

    主要作用是用来提高某些特定场景的性能什么是 React Fiber?Fiber 是 React 16 中新的协调引擎或重新实现核心算法。它的主要目标是支持虚拟DOM的增量渲染。...React Fiber 的目标是增强其在动画、布局和手势等领域的适用性。它的主要特性是增量渲染:能够将渲染工作分割成块,并将其分散到多个帧中。React 父组件如何调用子组件中的方法?...这种方式很少被使用,咱们可以将一个函数传递给setState,该函数接收上一个 state 的值和当前的props,并返回一个新的状态,如果咱们需要根据以前的状态重新设置状态,推荐使用这种方式。...,例如: this.info = ele}>createRef方法:React 16提供的一个API,使用React.createRef()来实现        在...(比如)和一个关闭标签(比如)之间的内容会作为一个特殊的属性props.children被自动传递给包含着它的组件。

    1.7K30

    React 进阶 - Ref

    # Ref # Ref 对象创建 ref 对象就是用 createRef 或者 useRef 创建出来的对象,一个标准的 ref 对象应该是如下的样子: { current: null, // current...,这样更方便后续操作 Ref 注意:不要在函数组件中使用 createRef,否则会造成 Ref 对象内容丢失等情况 函数组件 useRef:可以用 hooks 中的 useRef export default...,因为 useRef 始终指向一个内存空间,所以这样一点好处是可以随时访问到变化后的值` const toLearn = [ { type: 1, msg: 'Let us learn React'...Ref 原理 对于 Ref 标签引用,React 是如何处理的呢?...会清空之前 ref 值,使其重置为 null 第二阶段:DOM 更新阶段,这个阶段会根据不同的 effect 标签,真实的操作 DOM 第三阶段:layout 阶段,在更新真实元素节点之后,此时需要更新

    1.7K10

    React源码解析之React.createRef()forwardRef()

    /packages/react/src/ReactCreateRef.js 作用: 获取目标element的DOM实例 使用: import React from 'react' export default...不可变的对象 //没见过这种写法 :RefObject export function createRef(): RefObject { //初始化ref对象,属性current初始值为null...实例 使用: import React from 'react' //funciton component是没有dom实例的,因为它是PureComponent,所以没有this, // 所以不能通过createRef...}; } 解析: (1)不看__DEV__的话,返回的也是一个Object,也就是说,Child被forwardRef包裹后,React.forwardRef(Child)的$$typeof是REACT_FORWARD_REF_TYPE...,请参考:https://reactjs.org/docs/react-api.html#reactforwardref (3)如何在antdPro/FunctionComponent中使用: 子: const

    1.6K20

    90行代码,15个元素实现无限滚动

    随着社交媒体的流行,大量的数据被用户消费。无线滚动提供了一个高效的方法让用户浏览海量信息,而不必等待页面的预加载。 ? 如何构建一个体验良好的无限滚动,是每个前端无论是项目或面试都会碰到的一个课题。...IntersectionObserverEntry对象) 这个对象有很多属性,其中最常用的属性是: target: 被观察的目标元素,是一个 DOM 节点对象 isIntersecting: 是否进入可视区域...intersectionRatio: 相交区域和目标元素的比例值,进入可视区域,值大于0,否则等于0 2.3 options 调用IntersectionObserver时,除了传一个回调函数,还可以传入一个...变量解析 start:当前渲染的列表第一个数据,默认为0 end: 当前渲染的列表最后一个数据,默认为15 observer: 当前观察的视图ref元素 6. useRef 定义追踪的DOM 元素 const...start - 10 : 0); // 头部元素索引最小值为0 setStart(newStart) setEnd(newEnd) } }); }

    3K20

    【React】1260- 聊聊我眼中的 React Hooks

    诚然,Hooks 解决了 React Mixins 这个老大难的问题,但从它各种奇怪的使用体验上来说,我认为现阶段的 Hooks 并不是一个好的抽象。...useRef 的「排除万难」 从本义上来说,useRef其实是 Class Component 时代React.createRef()的等价替代。...这意味着一次完整的生命周期中,useRef保留的引用始终不会改变。 而这一特点却让它成为了 Hooks 闭包救星。 「遇事不决,useRef !」...也就是说,Class Component 和 Function Component 的生命周期 API 并不能完全一一对应,这是一个很引发错误的地方。...Hooks 为 Function Component 赋予了 State 能力并提供了生命周期,使 Function Component 的大规模使用成为了可能。

    1.1K20

    为了学好 React Hooks, 我抄了 Vue Composition API, 真香

    而且它简单易学, 这简直是 Vue 开发者的‘福报‘啊! 是不是也想自己动手写一个?把 VCA 搬到 React 这边来,解决这些问题?...我们带着这些问题,一步一步来实现这个 ‘React Composition API’ 响应式数据和 ref 如何实现数据的响应式?不需要我们自己去造轮子,现成最好库的是 MobX。...看下面的例子, 思考一下响应是怎么丢失的: const data = reactive({count: 1}) // 解构, 响应丢失了. // 这时候 count 只是一个普通的、值为1的变量. /...包装 Props 为响应式数据 React 组件每次重新渲染都会生成一个新的 Props 对象,所以无法直接在 setup 中使用,我们需要将其转换为一个可以安全引用的对象,然后在每次重新渲染时更新这个对象...总结 最后,这只是一个玩具?!整个过程也不过百来行代码。

    3.1K20

    React系列-轻松学会Hooks

    class的setState 如何使用 useState接受一个参数,返回了一个数组 // 使用es6解构赋值,useState(0)的意思是给count赋予初始值0 // count是一个状态值...componentDidMount:通过 useEffect 传入第二个参数为[]实现。 componentDidUpdate:通过 useEffect 传入第二个参数为空或者为值变动的数组。...如何使用 const refContainer = useRef(initialValue) 知识点合集 获取DOM元素的节点 useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数...注意:createRef 每次渲染都会返回一个新的引用,而 useRef 每次都会返回相同的引用。...具体关于(ref React.createRef useRef、React.forwardRef这些形式我会单独抽一个章节来讲到) 获取子组件的实例 // 实际就是利用了一个回调 const Child2

    4.4K20

    React Hooks 万字总结

    (initialState) useState 有一个参数,该参数可以为任意数据类型,一般用作默认值 useState 返回值为一个数组,数组的第一个参数为我们需要使用的 state,第二个参数为一个...返回的 ref 对象在组件的整个生命周期内保持不变 解决引用问题--useRef 会在每次渲染时返回同一个 ref 对象 解决一些 this 指向问题 对比 createRef -- 在初始化阶段两个是没区别的...所以我们每更新一次组件, 就重新创建一次 ref, 这个时候继续使用 createRef 显然不合适,所以官方推出 useRef。...useRef 创建的 ref 仿佛就像在函数外部定义的一个全局变量,不会随着组件的更新而重新创建。...一个项目要做 pc 站点又要做移动端,在不考虑双端业务是否合理的情况下,这种情况 ui 能复用的地方不太多,但是业务逻辑能大量通过 hooks 进行复用,也算是是一个伪逻辑跨端 总结 越来越多的 react

    94420

    React实战精讲(React_TSAPI)

    下⾯我们来举⼏个例⼦,介绍⼀下如何使⽤泛型约束。 确保属性存在 有时候,我们希望「类型变量对应的类型上存在某些属性」。这时,除⾮我们显式地将特定属性定义为类型变量,否则编译器不会知道它们的存在。...❞ ---- 类型化 useRef useRef 有两个主要用途 保存一个「自定义的可变值」(它的值变更不会触发更新)。 保持对一个DOM对象的引用 类型化可变值 它基本上与 useState 相同。...想让useRef保存一个自定义的值,你需要告诉它这个类型。...首先,为context的「值」创建一个类型,然后把它作为一个「泛型」提供给createContext函数。...如何解决context的值可能是未定义的情况呢。我们针对context的获取可以使用一个「自定义的hook。」

    10.4K30

    07-React Hooks(路由组件懒加载, Context上下文, 组件优化...)

    * 2.1: const [count, setCount] = useState(0) * 2.2: 调用useState 入参为初次属性初始化的默认值 * 2.3: 返回值为数组,一般使用结构的方式获取回来..., 第一个引用为值对象, 第二个引用为该值对象的赋值函数 * 3: 渲染方式, 直接通过 {count} 渲染 * 4: 赋值方式: 调用赋值函数 * 4.1: 入参为值对象修改 setCount...(count+1) * 4.2: 入参为函数修改: setCount(count => count + 1) 函数会有一个入参为当前值对象, 然后需要返回一个新的值对象 */ import React...default Index; useRef /** * 使用范围: 用于函数式组件, 使函数式组件具备React.createRef的能力 * useRef的使用方式 * 1: 从react库中引入...+hooks来写的 render props 如何向组件内部动态传入带内容的结构(标签)?

    1.3K30

    这个 hook api,是 useState 的双生兄弟

    使用函数创建组件,有一个非常特殊的地方。那就是当组件重新刷新时,组件函数会重新执行。于是在这种情况下,如何在函数内部持久化保存一个数据或者状态就变成了一个需要探讨的问题。...因此当我们在考虑需要持久化一个数据时,一定要区分清楚该数据自身的特性。 当该需要持久化的数据不会跟 UI 变化产生关系时,我们就需要用到 useRef。 useRef 是一个返回可变引用对象的函数。...该对象 .current 属性的初始值为 useRef 传入的参数 initialValue 返回的对象将在组件整个生命周期中持续存在。...,其实也是一个需要持久化的对象,因此使用 useRef 来保存引用是非常合适的。... input = node} /> 但是在函数组件中,由于我们还要思考如何使用一个引用稳定的变量来关联节点,这会比直接使用useRef

    1.1K20
    领券