web-dev-qa-db-fra.com

ReactJS: setTimeout () ne fonctionne pas?

Ayant ce code en tête: 

var Component = React.createClass({

    getInitialState: function () {
        return {position: 0};    
    },

    componentDidMount: function () {
        setTimeout(this.setState({position: 1}), 3000);
    },

    render: function () {
         return (
            <div className="component">
                {this.state.position}
            </div>
         ); 
    }

});

ReactDOM.render(
    <Component />,
    document.getElementById('main')
);

L'état n'est-il pas censé changer seulement après 3 secondes? Cela change immédiatement. 

Mon objectif principal ici est de changer l'état toutes les 3 secondes (avec setInterval()), mais comme cela ne fonctionnait pas, j'ai essayé setTimeout(), qui ne fonctionne pas non plus. Des lumières sur ça? Merci!

54
jbarradas

Faire

setTimeout(
    function() {
        this.setState({position: 1});
    }
    .bind(this),
    3000
);

Sinon, vous passez le résultat de setState à setTimeout.

143
Daniel A. White
setTimeout(() => {
  this.setState({ position: 1 });
}, 3000);

Ce qui précède fonctionnerait également car la fonction de flèche ES6 ne modifie pas le contexte de this.

104
Steven Scaffidi

Chaque fois que nous créons un délai d’expiration, nous devrions l’effacer sur le composantWillUnmount, s’il ne s’est pas encore déclenché.

      let myVar;
         const Component = React.createClass({

            getInitialState: function () {
                return {position: 0};    
            },

            componentDidMount: function () {
                 myVar = setTimeout(()=> this.setState({position: 1}), 3000)
            },

            componentWillUnmount: () => {
              clearTimeout(myVar);
             };
            render: function () {
                 return (
                    <div className="component">
                        {this.state.position}
                    </div>
                 ); 
            }

        });

ReactDOM.render(
    <Component />,
    document.getElementById('main')
);
15
Khalid Azam

setState est invoqué immédiatement en raison de la parenthèse! Enveloppez-le dans une fonction anonyme, puis appelez-le:

setTimeout(function() {
    this.setState({position: 1})
}.bind(this), 3000);
6
tymeJV

Votre portée de code (this) sera votre objet window, pas votre composant react, et c’est pourquoi setTimeout(this.setState({position: 1}), 3000) plantera de cette façon.

Cela vient de javascript pas react, c'est js fermeture


Ainsi, afin de lier la portée de votre composant de réaction actuel, procédez comme suit:

setTimeout(function(){this.setState({position: 1})}.bind(this), 3000);

Ou, si votre navigateur prend en charge es6 ou si votre projet prend en charge la compilation de es6 à es5, essayez également arrow, car arrow func corrige ce problème:

setTimeout(()=>this.setState({position: 1}), 3000);
4
Xin Wang

Je sais que cela est un peu vieux, mais il est important de noter que React recommande d'effacer l'intervalle lorsque le composant se démonte: https://reactjs.org/docs/state-and-lifecycle.html

J'aime donc ajouter cette réponse à cette discussion:

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }
  componentWillUnmount() {
    clearInterval(this.timerID);
  }
4
Fernando Lopes

Il y a 3 façons d'accéder à la portée à l'intérieur de la fonction 'setTimeout'

Premier,

const self = this
setTimeout(function() {
  self.setState({position:1})
}, 3000)

Deuxièmement, il faut utiliser la fonction flèche ES6, la fonction flèche n’ayant pas elle-même de portée (ceci)

setTimeout(()=> {
   this.setState({position:1})
}, 3000)

La troisième consiste à lier la portée à l'intérieur de la fonction

setTimeout(function(){
   this.setState({position:1})
}.bind(this), 3000)
2
Darryl Fabian

Vous n'avez pas dit qui a appelé setTimeout

Voici comment vous appelez timeout sans appeler de fonctions supplémentaires.

1. Vous pouvez le faire sans créer de fonctions supplémentaires.

setTimeout(this.setState.bind(this, {position:1}), 3000);

Utilise function.prototype.bind ()

setTimeout prend l'emplacement de la fonction et le conserve dans le contexte.

2. Une autre façon de faire la même chose en écrivant encore moins de code.

setTimeout(this.setState, 3000, {position:1});

Probablement utilise la même méthode bind à un moment donné

Le setTimeout prend seulement l'emplacement de la fonction et la fonction a déjà le contexte? En tout cas, ça marche!

NOTE: Celles-ci fonctionnent avec toutes les fonctions que vous utilisez en js.

2
Advis

Vous avez commis une erreur de déclaration de syntaxe, utilisez la déclaration setTimeout appropriée 

message:() => { 
  setTimeout(() => {this.setState({opened:false})},3000); 
  return 'Thanks for your time, have a Nice day ????! 
}
0
KARTHIKEYAN.A