Я пытался изо всех сил пытаться придумать способ использования setTimeout
, как вы пытались сделать в функциональном компоненте, но, как вы поняли, есть проблема с крошечным временем между рендерингом и сбросом тайм-аут.
Лучшее, что я мог придумать, это просто использовать setInterval
. Если вы не уверены, как использовать это с крючками, я сделал быстрый кодовый ящик с моими экспериментами: https://codesandbox.io/s/rough-shape-rjmjs
Ключ в том, что мы устанавливаем интервал один раз и удаляем только при размонтировании, поэтому он постоянно тикает интервал закрывается по начальному состоянию, например:
setCount(c => {
// c is the most recent count state
if (c > 0) {
return c - 1;
}
return c;
});
Если это не соответствует вашим потребностям, я также добавил второй, где он также использует ссылку для обхода проблемы закрытия. Мы просто вызываем функцию, назначенную для ссылки, на каждый интервал, но мы переназначаем, какую функцию выполняет каждый рендеринг.
timerLogicRef.current = () => {
if (otherCount > 0) {
setOtherCount(otherCount - 1);
}
};
Возможно, будет проще выполнить второе согласование с настройкой вашего редуктора.