Хук Preact setState не будет работать в пределах setInterval - PullRequest
1 голос
/ 26 апреля 2019

CodeSandbox
Попытка useState внутри setInterval из preact/hook. Это не работает, похоже, что для любой итерации он выполняет предыдущие стеки вызовов (?). Может ли кто-нибудь помочь мне понять и помочь мне исправить этот фрагмент?

import {h} from 'preact';
import {useState} from 'preact/hooks'
const interests = [
  {name: 'the future',},
  {name: 'architecture',},
  {name: 'my work',},
  {name: 'your work',},
  {name: 'collaboration',},
  {name: 'dank memes',},
  {name: 'OOP vs. Functional',},
  {name: 'design',},
  {name: 'guitar',},
  {name: 'inspirational people',},
  {name: 'love',},
  {name: 'travel',},
  {name: 'singularity',},
  {name: 'creativity',},
  {name: 'mixed, virtual, augmented reality',},
  {name: 'art',},
  {name: 'imagination',},
  {name: 'problem solving',},
  {name: 'space',},
  {name: 'cooking',},
  {name: 'FOMO',},
  {name: 'ontological design',},
  {name: 'flow state',},
  {name: 'foreign languages',},
  {name: 'streaming on the internet',},
  {name: 'video games',},
  {name: 'coffee',},
  {name: 'crypto currency',},
  {name: 'javascript fatigue',},
  {name: 'framework wars',},
  {name: 'blockchain',},
  {name: 'smart contracts',},
  {name: 'just emailing me'},
  {name: 'ethereum'},
  {name: 'university'},
  {name: 'engineering software'},
];


const RunningHeader = () => {
  const [count, setCount] = useState(0);
  setInterval(() => {setCount(c => c + 1)}, 1000);
  return (
    <header>
      <p>{interests[count].name}</p>
    </header>
)}

export {RunningHeader};

Ответы [ 2 ]

2 голосов
/ 26 апреля 2019

Вам нужно использовать setTimeout. setInterval никогда не отменяется, поэтому каждый рендер добавляет новый таймер повторения 1 с. Вот ваша песочница, исправленная двумя различными способами (setTimeout или с помощью useEffect для установки повторяющегося таймера при монтировании):

https://codesandbox.io/s/vy0ww725j0

1 голос
/ 26 апреля 2019

useEffect без зависимостей [] будет действовать как componentDidMount для монтирования нашего интервала, и мы можем вернуть функцию, которая будет вызываться при размонтировании, мы должны очистить наш интервал при размонтировании, чтобы избежать утечек памяти.

useEffect(() => {
  const id = setInterval(() => {
    setCount(c => c + 1);
  }, 1000);
  return () => clearInterval(id);
}, []);
...