How to add “refs” dynamically with react hooks?

后端 未结 3 1441
粉色の甜心
粉色の甜心 2020-12-08 10:38

So I have an array of data in and I am generating a list of components with that data. I\'d like to have a ref on each generated element to calculate the height. I know how

相关标签:
3条回答
  • 2020-12-08 10:55

    I created a tiny npm package that exposes a React Hook to handle setting and getting refs dynamically as I often run into the same problem.

    npm i use-dynamic-refs
    

    Here's a simple example.

    import React, { useEffect } from 'react';
    import useDynamicRefs from 'use-dynamic-refs';
    
    const Example = () =>  {
      const foo = ['random_id_1', 'random_id_2'];
      const [getRef, setRef] =  useDynamicRefs();
    
      useEffect(() => {
        // Get ref for specific ID 
        const id = getRef('random_id_1');
        console.log(id)
      }, [])
    
        return ( 
          <>
            {/* Simple set ref. */}
            <span ref={setRef('random_id_3')}></span>
    
             {/*  Set refs dynamically in Array.map() */}
            { foo.map( eachId => (
              <div key={eachId} ref={setRef(eachId)}>Hello {eachId}</div>))}
          </>
        )
    }
    
    export default Example;
    
    0 讨论(0)
  • 2020-12-08 11:03

    You have to use a separate set of hooks for each item, and this means you have to define a component for the items (or else you’re using hooks inside a loop, which isn’t allowed).

    const Item = ({ text }) => {
        const ref = useRef()
        const [ height, setHeight ] = useState()
        useLayoutEffect(() => {
            setHeight( ref.current.getBoundingClientRect().height )
        }, [])
        return <div ref={ref}>{text}</div>
    }
    
    0 讨论(0)
  • 2020-12-08 11:15

    Not sure i fully understand your intent, but i think you want something like this:

    const {
      useState,
      useRef,
      createRef,
      useEffect
    } = React;
    
    const data = [
      {
        text: "test1"
      },
      {
        text: "test2"
      }
    ];
    
    const Component = () => {
      const [heights, setHeights] = useState([]);
      const elementsRef = useRef(data.map(() => createRef()));
    
      useEffect(() => {
        const nextHeights = elementsRef.current.map(
          ref => ref.current.getBoundingClientRect().height
        );
        setHeights(nextHeights);
      }, []);
    
      return (
        <div>
          {data.map((item, index) => (
            <div ref={elementsRef.current[index]} key={index} className={`item item-${index}`}>
              {`${item.text} - height(${heights[index]})`}
            </div>
          ))}
        </div>
      );
    };
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<Component />, rootElement);
    .item {
      box-sizing: border-box;
      display: flex;
      align-items: center;
      justify-content: center;
      border: 1px solid #ccc;
    }
    
    .item-0 {
      height: 25px;
    }
    
    .item-1 {
      height: 50px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
    <div id="root"/>

    0 讨论(0)
提交回复
热议问题