2
votes

Comment obtenir setInterval pour exécuter la fonction de rappel une fois avant d'appliquer le délai

J'exécute setInterval dans useEffect hook pour boucler une fonction, cependant, je veux pouvoir exécuter cette fonction une fois avant d'appliquer le délai (intervalle). Existe-t-il un moyen d'exécuter la fonction une fois dans le hook useEffect avant d'appliquer le délai?

J'ai essayé d'exécuter la fonction une fois à l'intérieur du hook avant la fonction setInterval mais cela ne m'a pas donné les résultats que j'espérais. Il en va de même pour l'exécution de la fonction en dehors du hook useEffect.

  const myText = props.text;
  const textTimeout = 100;
  const funTextInterval = textTimeout * myText.length
  const [quickText, setQuickText] = useState([]);

  const setDelay = (i) => {
    setTimeout(() => {
       myFunction();
     , textTimeout * i);
  };

  useEffect(() => {
    setInterval(() => {
      for (let i = 0; i < myText.length + 1; i++) {
        setDelay(i);
      }
    }, funTextInterval);    
  }, []);

Je m'attends à ce que le forloop s'exécute une fois avant que le délai de setInterval ne commence, mais le délai se produit avant le code forloop >


2 commentaires

Êtes-vous sûr que le délai ne provient pas de setTimeout () plutôt que de l'intervalle?


^^ Cela. Une combinaison de setInterval () et setTimeout () est à l'origine de votre problème.


3 Réponses :


1
votes

Vous pouvez séparer votre logique comme ceci:

  const myText = props.text;
  const textTimeout = 100;
  const funTextInterval = textTimeout * myText.length
  const [quickText, setQuickText] = useState([]);

  function applyTextEffect() {
      for (let i = 0; i < myText.length + 1; i++) {
        setTimeout(myFunction, textTimeout * i);
      }
  }

  useEffect(() => {
    applyTextEffect()  // call it here immediately to get the effect you want.
    setInterval(applyTextEffect, funTextInterval);    
  }, []);

Mais notez que ce composant créera un effet indésirable en appelant votre fonction d'effet de texte à chaque mise à jour. UseEffect fonctionne dans chaque mise à jour. Mieux vaut avoir une variable d'état isMounted et implémenter une logique autour d'elle pour appliquer l'effet une seule fois.

EDIT: Il est également sage de stocker l'ID d'intervalle retourné par la fonction setInterval et de l'effacer en retour de useEffect. Sinon, lorsque votre composant va être détruit, vous obtiendrez des exceptions


0 commentaires

0
votes

écrivez une fonction séparée uniquement avec la boucle for.
appelez cette fonction avant d'appeler useEffect ().
depuis useEffect () -> setInterval (), appelez la nouvelle méthode.

Le code non testé est donné ci-dessous à titre d'illustration.

const myText = props.text;
const textTimeout = 100;
const funTextInterval = textTimeout * myText.length
const [quickText, setQuickText] = useState([]);

const setDelay = (i) => {
  setTimeout(() => {
     myFunction();
   , textTimeout * i);
};

runloop(){
  for (let i = 0; i < myText.length + 1; i++) {
    setDelay(i);
  }
}

useEffect(() => {
  setInterval(() => {
    runloop()
  }, funTextInterval);    
}, []);

runloop();


0 commentaires

1
votes

Sortez la logique de la boucle for dans une méthode et appelez-la avant setInterval et à l'intérieur de setInterval

const myText = props.text;
  const textTimeout = 100;
  const funTextInterval = textTimeout * myText.length
  const [quickText, setQuickText] = useState([]);

  const setDelay = (i) => {
    setTimeout(() => {
       myFunction();
     , textTimeout * i);
  };

  useEffect(() => {
    const loop = () => {
      for (let i = 0; i < myText.length + 1; i++) {
        setDelay(i);
      }
    }
    loop();
    setInterval(() => {
      loop();
    }, funTextInterval);    
  }, []);


0 commentaires