Как я могу использовать несколько ссылок для массива элементов с крючками? - PullRequest
0 голосов
/ 11 февраля 2019

Насколько я понял, я могу использовать ссылки для одного элемента, подобного этому:

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>

Я видел это и, следовательно, это .Но я все еще не понимаю, как реализовать это предложение для этого простого случая.

Ответы [ 3 ]

0 голосов
/ 11 февраля 2019

Обратите внимание, что вы не должны использовать useRef в цикле по простой причине: порядок используемых хуков имеет значение!

Документация гласит

Не вызывать хуки внутри циклов, условий или вложенных функций.Вместо этого всегда используйте Hooks на верхнем уровне вашей функции React.Следуя этому правилу, вы гарантируете, что хуки вызываются в одном и том же порядке каждый раз при рендеринге компонента.Это то, что позволяет React правильно сохранять состояние хуков между несколькими вызовами useState и useEffect.(Если вам интересно, мы объясним это подробно ниже.)

Но учтите, что это, очевидно, относится к динамическим массивам ... но если вы используете статические массивы (вы ВСЕГДА визуализируетеодинаковое количество компонентов) не беспокойтесь об этом, знайте, что вы делаете, и используйте это ?

0 голосов
/ 09 мая 2019

Поскольку вы не можете использовать зацепки внутри циклов , вот решение для того, чтобы заставить его работать, когда массив изменяется со временем.

Я полагаю, массив поступает из подпорок:

const App = props => {
    const itemsRef = useRef([]);
    // you can access the elements with itemsRef.current[n]

    useEffect(() => {
       itemsRef.current = itemsRef.current.slice(0, props.items.length);
    }, [props.items]);

    return props.items.map((item, i) => (
      <div 
          key={i} 
          ref={el => itemsRef.current[i] = el} 
          style={{ width: `${(i + 1) * 100}px` }}>
        ...
      </div>
    ));
}
0 голосов
/ 11 февраля 2019

Ссылка изначально просто { current: null } объект.useRef сохраняет ссылку на этот объект между компонентами рендеринга.Значение current в основном предназначено для ссылок на компоненты, но может содержать что угодно.

В какой-то момент должен быть массив ссылок.В случае фиксированной длины массива это может быть:

  const elRef = useRef([...Array(3)].map(() => createRef()));
  ...  
  return (
    <div>
      {[1, 2, 3].map((el, i) => (
        <div ref={elRef.current[i]} style={{ width: `${el * 100}px` }}>...</div>
      ))}
    </div>
  );
...