React Hooks: карусель автозапускается до нажатия кнопки и не завершает последний оставшийся setTimeout () - PullRequest
1 голос
/ 02 октября 2019

Я делаю своего рода карусель в React.

function CareersReasonsCarousel(props) {
    const [current, setCurrent] = useState(0);
    const [dir, setDir] = useState("next");
    const [auto, setAuto] = useState(true);

    const move = (pos) => {
        setAuto(false);
        setCurrent(current+pos);
    }

    useEffect(() => {
        setTimeout(() => {
            if (auto) {
                setCurrent(current+1);
            }
        }, 5000);
    }, [current]);
}

И ниже, в моем return, у меня есть

<div className="arrow next" onClick={ () => { move(1) }}><img src={ arrow_right } alt="" /></div>

Я хочу, чтобы карусель началасьАвтовоспроизведение, когда страница загружается впервые, и теряет автовоспроизведение, когда кто-то нажимает стрелки «следующий» или «предыдущий». Проблема в том, как он настроен, когда я нажимаю стрелки, карусель все еще будет ждать оставшуюся 5-секундную задержку и выполнит последний зарегистрированный «setTimeout», и только тогда она увидит, что autofalse и больше не нужно его автоматизировать.

Как я могу получить его для проверки значения auto, не при регистрации setTimeout, но когда он должен быть выполнен (послеЗадержка 5 секунд)?

Спасибо!

1 Ответ

2 голосов
/ 02 октября 2019

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

const timerRef = useRef(null)

useEffect(() => {
    if(timerRef.current){
        clearTimeout(timerRef.current);
    }
    timerRef.current = setTimeout(() => {
        if (auto) {
            setCurrent(c=>c+1);
        }
    }, 5000);
    return ()=>clearTimeout(timerRef.current);
}, [auto, current]);
...