小编典典

如何对带有钩子的元素数组使用多个引用?

reactjs

据我了解,我可以将refs用于单个元素,如下所示:

const { useRef, useState, useEffect } = React;



const App = () => {

  const elRef = useRef();

  const [elWidth, setElWidth] = useState();



  useEffect(() => {

    setElWidth(elRef.current.offsetWidth);

  }, []);



  return (

    <div>

      <div ref={elRef} style={{ width: "100px" }}>

        Width is: {elWidth}

      </div>

    </div>

  );

};



ReactDOM.render(

  <App />,

  document.getElementById("root")

);


<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>

<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>



<div id="root"></div>

如何为一系列元素实现此功能?显然不是这样:(即使我没有尝试,我也知道:)

const { useRef, useState, useEffect } = React;



const App = () => {

  const elRef = useRef();

  const [elWidth, setElWidth] = useState();



  useEffect(() => {

    setElWidth(elRef.current.offsetWidth);

  }, []);



  return (

    <div>

      {[1, 2, 3].map(el => (

        <div ref={elRef} style={{ width: `${el * 100}px` }}>

          Width is: {elWidth}

        </div>

      ))}

    </div>

  );

};



ReactDOM.render(

  <App />,

  document.getElementById("root")

);


<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>

<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>



<div id="root"></div>

我已经看到了这个,因此这个。但是,对于这种简单情况,我仍然感到困惑。


阅读 217

收藏
2020-07-22

共1个答案

小编典典

ref最初只是{ current: null }对象。useRef在组件渲染之间保留对此对象的引用。currentvalue主要用于组件引用,但可以容纳任何内容。

在某个时候应该有一组引用。如果渲染之间数组长度可能有所不同,则数组应相应缩放:

  const arrLength = arr.length;
  const [elRefs, setElRefs] = React.useState([]);

  React.useEffect(() => {
    // add or remove refs
    setElRefs(elRefs => (
      Array(arrLength).fill().map((_, i) => elRefs[i] || createRef())
    ));
  }, [arrLength]);

  return (
    <div>
      {arr.map((el, i) => (
        <div ref={elRefs[i]} style={...}>...</div>
      ))}
    </div>
  );

可以通过解包useEffect和替换来优化这段代码useStateuseRef但应注意,通常认为在render函数中产生副作用是一种不好的做法:

  const arrLength = arr.length;
  const elRefs = React.useRef([]);

  if (elRefs.current.length !== arrLength) {
    // add or remove refs
    elRefs.current = Array(arrLength).fill().map((_, i) => elRefs.current[i] || createRef())
    ));
  }

  return (
    <div>
      {arr.map((el, i) => (
        <div ref={elRefs.current[i]} style={...}>...</div>
      ))}
    </div>
  );
2020-07-22