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

#javascript #reactjs #react-hooks #setinterval

Вопрос:

Я привел этот пример codesandbox, чтобы проиллюстрировать свою проблему. Я хотел бы несколько раз использовать компонент React на одной странице, который принимает массив изображений и автоматически просматривает их (используя CSS через z-индекс или дисплей).

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

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

Спасибо!

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

1. Пожалуйста, вставьте свой код в сам вопрос.

Ответ №1:

Ваша проблема не в setInterval том, а в том, как вы извлекаете список слайдов из ImageSwapper своего компонента: document.getElementsByClassName("photo");

Поскольку все ваши изображения имеют photo класс, каждый ImageSwapper компонент будет перебирать все изображения, а не только их дочерние элементы.

Простое решение, учитывая ваш подход, состоит в том, чтобы назначить каждому уникальный идентификатор ImageSwapper и использовать этот идентификатор для группировки изображений по классам (допустим, класс будет photo_ id }:

 <ImageSwapper title="box 1" id="box_1">
      <img src="..." className="photo_box_1"/>
      <img src="..." className="photo_box_1"/>
      <img src="..." className="photo_box_1"/>
</ImageSwapper>
<ImageSwapper title="box 2" id="box_2">
      <img src="..." className="photo_box_2"/>
      <img src="..." className="photo_box_2"/>
      <img src="..." className="photo_box_2"/>
</ImageSwapper>
 

Затем в ImageSwapper вы можете получить слайды, подобные этому:

 const ImageSwapper = ({ children, title, id }) => {
  var slides = document.getElementsByClassName(`photo_${id}`);
...
}
 

Рабочий стекблитц

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

1. Спасибо! Это действительно круто и работает, но сейчас моя проблема в том, что скрипт не запускается, когда пользователь покидает страницу. Это вызывает у меня ошибки в разработке «Несколько необработанных ошибок во время выполнения, обнаруженных в ваших файлах».

2. Это совсем другая проблема. setInterval установит таймер глобально, и ваш компонент будет вызывать setInterval каждый раз, когда он отображается. Так что в итоге у вас будет много таймеров, которые вы не убираете! Вы можете проверить ответ @DerekReilly на удаление с помощью этого.

Ответ №2:

Я предложил вам проверить эту реализацию крючка useInterval: https://usehooks-typescript.com/react-hook/use-interval

 import { useEffect, useRef } from 'react'
function useInterval(callback: () => void, delay: number | null) {
    const savedCallback = useRef(callback)

// Remember the latest callback if it changes.
useEffect(() => {
    savedCallback.current = callback
 }, [callback])

// Set up the interval.
useEffect(() => {
  // Don't schedule if no delay is specified.
  if (delay === null) {
    return
  }

  const id = setInterval(() => savedCallback.current(), delay)

  return () => clearInterval(id)
}, [delay])
}
export default useInterval
 

И если вам интересно, прочтите прилагаемый пост в блоге Дэна Абромова:
https://overreacted.io/making-setinterval-declarative-with-react-hooks/

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

1. Спасибо за советы, я посмотрю сейчас и посмотрю, смогу ли я заставить его работать таким образом.