7

React を使用して、このように静的に宣言された ref のリストがあります。

  let line1 = useRef(null);
  let line2 = useRef(null);
  let line3 = useRef(null);
  ...
  //IN MY RENDER PART
  <li ref={(el) => (line1 = el)}>line1</li>
  <li ref={(el) => (line2 = el)}>line1</li>
  <li ref={(el) => (line3 = el)}>line1</li>

次に、参照がアニメーション関数に渡され、すべてが正しく機能します。少し状況が変わり、マップを使用してリスト項目を作成すると、要素を正しく参照できなくなりました。私は次のようなものを試しました:

{menu.menu.map((D) => {
let newRef = createRef();
                    LiRefs.push(newRef);
                    return (
                      <li
                        key={D.id}
                        ref={(el) => (newRef = el)} >
                        {D.label}
                      </li>
                    );
                  })}

しかし、アニメーション関数に渡す配列は空です (関数が useEffect フック内で呼び出され、LiRefs がまだ useRef ではないためだと思います)

  • 私は作成するので、最初にそれらを宣言し、次のような参照を行うことができます

    ref={(el) => (`line${i}` = el)}
    

    私が試すことができる他の解決策が機能していないのはどれですか?

  • 4

    3 に答える 3

    6

    私のは React Hooks バージョンです。

    useMemoパフォーマンスのために参照の配列を作成します。

    const vars = ['a', 'b'];
    const childRefs = React.useMemo(
        () => vars.map(()=> React.createRef()), 
        [vars.join(',')]
    );
    
    

    Reactは各参照をにマウントしますchildRefs

    {vars.map((v, i) => {
        return (
            <div>
                 <Child v={v} ref={childRefs[i]} />
                 <button onClick={() => showAlert(i)}> click {i}</button>
            </div>
        )
     })
    }
    

    これが実行可能なデモです。お役に立てば幸いです。^_^

    
    
    const Child = React.forwardRef((props, ref) => {
    
      React.useImperativeHandle(ref, () => ({
        showAlert() {
          window.alert("Alert from Child: " + props.v);
        }
      }));
    
      return <h1>Hi, {props.v}</h1>;
    });
    
    const App = () => {
      const vars = ['a', 'b'];
      const childRefs = React.useMemo(
        () => vars.map(()=> React.createRef()), 
        // maybe vars.length
        [vars.join(',')]
      );
      function showAlert(index) {
        childRefs[index].current.showAlert();
      }
      
      return (
        <div>
          {
            vars.map((v, i) => {
              return (
                <div>
                  <Child v={v} ref={childRefs[i]} />
                  <button onClick={() => showAlert(i)}> click {i}</button>
                </div>
              )
            })
          }
        </div>
      )
    }
    
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(
      <App />,
      rootElement
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
    
    <div id="root"></div>
    于 2021-01-20T03:38:32.717 に答える
    3

    他の回答には、Typescript の矛盾と複雑さがあるかもしれません。したがって、ループに useRef フックを使用する最良の方法は次のとおりだと思います。

    // Declaration
    const myRef = useRef([]);
    myRef.current = [];
    const addToRefs: (el) => void = (el) => {
      if (el && !myRef.current.includes(el)) {
        myRef.current.push(el);
      }
    };
    

    // Assignment (I will show an example for an input element)
    ...
    ...
    {anyArrayForLoop.map((item, index) => {
       return (
           <input
               key={index}
               ref={addToRefs}
           />
       );
    })}
    ...
    ...
    

    最後の:

    // The Data
    myRef.current // So you got em.
    
    于 2022-01-14T13:08:29.587 に答える