#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. Спасибо за советы, я посмотрю сейчас и посмотрю, смогу ли я заставить его работать таким образом.