Сопоставьте дочерние ссылки с родительским массивом

#javascript #reactjs

Вопрос:

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

Однако мне нужно хранить каждую ссылку в массиве.

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

Это делается для того, чтобы я мог отслеживать позиции элементов с помощью getBoundingClientRect() крючка

 export default function ({ children }) => {
  const itemsRef = useRef([]);

  console.log(itemsRef);
  // returns a ref containing an array
  // {current: Array(5)}
  
  // How could I modify what I am doing 
  // to to instead return an array of refs?
  // something like:
  // [{current: HTMLDivElement}, {current: HTMLDivElement}, .....]
  
  return (
    <>
      {React.Children.map(children, (child, index) =>
        React.cloneElement(child, {
          ref: (ref) => (
            <Item ref={(itemsRef.current[index] = ref)} key={index}>
              {child}
            </Item>
          )
        })
      )}
    </>
  );
};
 

Комментарии:

1. Прочитайте это , сохраняя массив элементов с помощью крючка useRef

Ответ №1:

Сначала создайте ссылки (того же размера, что и ваш массив) и передайте их своему компоненту. Я проверяю длину детей, потому что она может меняться между рендерами.

 export default function ({ children }) => {
  const itemsRef = useRef([]);
  const childrenLength = itemsRef;
  
  if (itemsRef.current.length != childrenLength) {
     itemsRef.current = Array(arrLength).fill().map((_, i) => itemsRef.current[i] || createRef());
  } 
  
  return (
    <>
      {React.Children.map(children, (child, index) =>
        React.cloneElement(child, {
          ref: (ref) => (
            <Item ref={itemsRef.current[index]} key={index}>
              {child}
            </Item>
          )
        })
      )}
    </>
  );
};
 

Ответ №2:

Это должно быть легко

Вот пример того, как бы я это сделал.

 export default function({children} : {children: React.ReactNode[]}) => {
  const itemsRef = useRef([]);

  console.log(itemsRef);

  refLoaded = () => {
    if (itemsRef.current.length == children.length) {
      // all ref are loaded, do you work here
    }
  }

  return (
  <> {
      children.map((child, index) => (
      <Item ref = {(c) => {
              if (c)
                itemsRef.current[index] = c;
            }
            key = {
              index
            }
            onLayout={refLoaded}>
            {child}
            </Item>
          )
        )
      } 
   </>
    );
  }; 

Комментарии:

1. Я думаю, что вы отвечаете, имея в виду React Native. Это просто реакция

2. Это должно работать на обоих, это не имеет ничего общего только с react native. его машинопись и реакция

3. Возможно, onLayout является родным для react, вместо этого вы могли бы добавить refLoaded в разделе ref