目标DOM如何在map中反应useRef [英] How target DOM with react useRef in map

查看:926
本文介绍了目标DOM如何在map中反应useRef的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一个关于使用react useRef() hook来获取DOM元素数组的解决方案。

I looking for a solution about get an array of DOM elements with react useRef() hook.

例如:

const Component = () => 
{

  // In `items`, I would like to get an array of DOM element
  let items = useRef(null);

  return <ul>
    {['left', 'right'].map((el, i) =>
      <li key={i} ref={items} children={el} />
    )}
  </ul>
}

我如何实现这一目标?

How can I achieve this?

推荐答案

useRef 与React的 ref (只是对象的结构,只有当前字段)。

useRef is just partially similar to React's ref(just structure of object with only field of current).

useRef hook的目标是在渲染之间存储一些数据并更改该数据不会触发重新渲染(与 useState 不同) 。

useRef hook is aiming on storing some data between renders and changing that data does not trigger re-rendering(unlike useState does).

同样温和提醒:最好避免在循环中初始化挂钩或如果。这是钩子的第一条规则

Also just gentle reminder: better avoid initialize hooks in loops or if. It's first rule of hooks.

记住这一点我们:


  1. 创建数组并保留它之间的渲染 useRef

  2. 我们通过 createRef()初始化每个数组的元素

  3. 我们可以使用 .current 表示法来引用列表

  1. create array and keep it between renders by useRef
  2. we initialize each array's element by createRef()
  3. we can refer to list by using .current notation

const Component = () => {

  let refs = useRef([React.createRef(), React.createRef()]);

  useEffect(() => {
    refs.current[0].current.focus()
  }, []);

  return (<ul>
    {['left', 'right'].map((el, i) =>
      <li key={i}><input ref={refs.current[i]} value={el} /></li>
    )}
  </ul>)
}


这是我们可以安全地修改数组(比如说)通过改变它的长度)。但是不要忘记 useRef 存储的变异数据不会触发重新渲染。因此,要更改长度以重新渲染,我们需要涉及 useState

This was we can safely modify array(say by changing it's length). But don't forget that mutating data stored by useRef does not trigger re-render. So to make changing length to re-render we need to involve useState.

const Component = () => {

  const [length, setLength] = useState(2);
  const refs = useRef([React.createRef(), React.createRef()]);

  function updateLength({ target: { value }}) {
    setLength(value);
    refs.current = refs.current.splice(0, value);
    for(let i = 0; i< value; i++) {
      refs.current[i] = refs.current[i] || React.createRef();
    }
    refs.current = refs.current.map((item) => item || React.createRef());
  }

  useEffect(() => {
   refs.current[refs.current.length - 1].current.focus()
  }, [length]);

  return (<>
    <ul>
    {refs.current.map((el, i) =>
      <li key={i}><input ref={refs.current[i]} value={i} /></li>
    )}
  </ul>
  <input value={refs.current.length} type="number" onChange={updateLength} />
  </>)
}

首次渲染时也不要尝试访问 refs.current [0] .current - 它会引发错误。

Also don't try to access refs.current[0].current at first rendering - it will raise an error.

Say

      return (<ul>
        {['left', 'right'].map((el, i) =>
          <li key={i}>
            <input ref={refs.current[i]} value={el} />
            {refs.current[i].current.value}</li> // cannot read property `value` of undefined
        )}
      </ul>)

所以要么保护它为

      return (<ul>
        {['left', 'right'].map((el, i) =>
          <li key={i}>
            <input ref={refs.current[i]} value={el} />
            {refs.current[i].current && refs.current[i].current.value}</li> // cannot read property `value` of undefined
        )}
      </ul>)

或在 useEffect hook中访问它。原因: ref s在元素渲染后被绑定,因此在渲染第一次运行时它尚未初始化。

or access it in useEffect hook. Reason: refs are bound after element is rendered so during rendering is running for the first time it is not initialized yet.

这篇关于目标DOM如何在map中反应useRef的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆