Обход массива, созданного с помощью useRef в React Native

У меня есть следующее в ответном собственном приложении:

export default function MyScreen() {

  const componentRefs = useRef([]);

  return (
            <View >
              {myArray.map(
                (wc, index) =>
                  (
                    <MyObject
                      key = {index}
                      ref = {el => componentRefs.current[index] = el}
                      index = {index}
                      // other props
                    />
                  )
              )}
            </View>
  );
}

Каждый экземпляр MyObject отображает слово. Хочу добавить функционал, который будет при нажатии кнопки выделять по очереди каждое слово и воспроизводить аудиофайл с его произношением.

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

Моя первоначальная попытка — использовать useRef для создания массива для хранения ссылок, как показано выше.

В качестве первоначального теста у меня есть обработчик кнопок, который проверяет, сохранены ли ссылки. Это просто перебирает каждый элемент в componentRefs:

componentRefs.current.forEach((x) => console.info(x));

Однако ничего не отображается. Также есть предупреждение:

Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Как лучше всего хранить ссылки в родительском элементе, чтобы обеспечить желаемую функциональность?

Большое спасибо

componentRefs.current.forEach но зачем тебе это нужно? Вы неправильно используете ссылку
Konrad 18.09.2023 11:29

Доступ к дочерним компонентам из родительского обычно является антишаблоном. Скорее всего, вы можете передать обратные вызовы и/или идентификаторы или использовать контекст для доступа к общему состоянию.

super 18.09.2023 11:42

@Конрад, ты можешь объяснить?

user1052610 18.09.2023 11:42

компонентRefs.current.forEach((x) => console.info(x)); ничего не выводит на консоль

user1052610 18.09.2023 11:48

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

Greedo 18.09.2023 11:49

@user1052610 user1052610 Он ничего не регистрирует, потому что массив пуст. Ты никогда ничего туда не кладешь. componentRefs[index] = <-- видишь... ? Я также хотел бы повторить, что это полный антипаттерн, и «решение этого» только создаст для вас больше проблем, поскольку вы пытаетесь заставить что-то вести себя так, как вы хотите, вместо того, чтобы научиться на самом деле использовать это.

super 18.09.2023 11:55

Спасибо. Как правильно это сделать? Если бы вы могли показать это в ответе, это было бы очень признательно.

user1052610 18.09.2023 11:56

Как я уже говорил: передайте обратный вызов и/или идентификатор или используйте контекст для общего состояния. Я не могу дать более конкретный ответ, поскольку вы опустили все детали, кроме того факта, что вы хотите поместить данные в массив из useRef. В общем, вы не хотите получать доступ к дочерним элементам от родителя. Вы хотите передавать вещи только вниз по иерархии. Я понятия не имею, какой у вас вариант использования.

super 18.09.2023 12:12

Почитайте, что такое проблема XY.

super 18.09.2023 12:15

Спасибо - отредактирую вопрос, чтобы лучше объяснить

user1052610 18.09.2023 12:19

Не следует редактировать стили, используя ссылку. Вы должны создать состояние и изменить состояние

Konrad 18.09.2023 13:20
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
11
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Пожалуйста, попробуйте использовать приведенный ниже код:

export default function App() {
  const componentRefs = useRef([]);
  useEffect(() => {
    Object.keys(componentRefs).map((item, i) => console.info(componentRefs[item]))
  }, [componentRefs]);
  return (
    <View>
      {myArray.map(
        (wc, index) =>
          (componentRefs[index] = (
            <MyObject
              key = {index}
              index = {index}
              // other props
            />
          ))
      )}
    </View>
  );
}

При использовании компонентаRefs.current.forEach ошибок нет, но ничего не отображается. При регистрации определенного элемента выводится сообщение «не определено».

user1052610 18.09.2023 12:11

можешь ли ты описать, что внутри MyObject?

Bluepanthor 18.09.2023 12:19

также получите предупреждение: функциональным компонентам нельзя давать ссылки. Попытки получить доступ к этой ссылке потерпят неудачу. Вы имели в виду использовать React.forwardRef()?

user1052610 18.09.2023 12:19

@user1052610 user1052610 Я отредактировал ответ, пожалуйста, просмотрите его.

Bluepanthor 18.09.2023 12:32

Это правильно регистрируется один раз (в useEffect), но не в обработчике кнопки, используя bcomComponentRefs.current.forEach((x) => console.info(x));

user1052610 18.09.2023 12:52

Принял этот ответ, большое спасибо. Остается одна проблема: как очистить массив компонентных ссылок. компонентRefs.current=[] и компонентRefs.current.length=0 не работают.

user1052610 18.09.2023 15:39

Используйте этот пример кода, чтобы использовать внутренний цикл useRef. Это всего лишь пример, меняйте компоненты по своему усмотрению.

export default function MyScreen() {
  const componentRefs = useRef([]);

  useEffect(() => {
    componentRefs.current.forEach(el => console.info(el));
  }, [componentRefs]);

  return (
    <div>
      {myArray.map(
        (wc, index) => (
          <MyObject
            key = {index}
            index = {index}
            componentRefs = {componentRefs}
            // other props
          />
        )
      )}
    </div>
  );
}
const MyObject = ({ index, componentRefs }) => {
  const ref = useRef(null);
  componentRefs.current[index] = ref;
  return (
    <View ref = {ref}>
      children
    </View>
  )
}

@user1052610 user1052610 Я снова отредактировал ответ. Теперь он должен предоставить вам все элементы внутри компонента Refs.current.

Akash Vichhi 18.09.2023 13:46

Другие вопросы по теме