ReactJS: setTimeout() werkt niet?

Met deze code in gedachten:

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')
);

Moet de status niet pas na 3 seconden veranderen? Het verandert meteen.

Mijn belangrijkste doel hier is om de status elke 3 seconden te wijzigen (met setInterval()), maar omdat het niet werkte, probeerde ik setTimeout(), wat werkt ook niet. Zijn hier lampjes op? Bedankt!


Antwoord 1, autoriteit 100%

Doe

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

Anders geef je het resultaat van setStatedoor aan setTimeout.

U kunt ook ES6-pijlfuncties gebruiken om het gebruik van thiszoekwoord te vermijden:

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

Antwoord 2, autoriteit 57%

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

Het bovenstaande zou ook werken omdat de ES6-pijlfunctie de context van thisniet verandert.


Antwoord 3, autoriteit 9%

Telkens wanneer we een time-out maken, moeten we deze wissen op componentWillUnmount, als deze nog niet is geactiveerd.

     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')
);

Antwoord 4, autoriteit 5%

Ik weet dat dit een beetje oud is, maar het is belangrijk op te merken dat React aanbeveelt om het interval te wissen wanneer het onderdeel wordt ontkoppeld: https://reactjs.org/docs/state-and-lifecycle.html

Dus ik voeg dit antwoord graag toe aan deze discussie:

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

Antwoord 5, autoriteit 3%

setStatewordt onmiddellijk aangeroepen vanwege de haakjes! Wikkel het in een anonieme functie en noem het dan:

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

Antwoord 6, autoriteit 3%

Je hebt niet verteld wie setTimeout heeft gebeld

Hier ziet u hoe u een time-out oproept zonder extra functies aan te roepen.

1. U kunt dit doen zonder extra functies te maken.

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

Gebruikt function.prototype.bind()

setTimeout neemt de locatie van de functie en houdt deze in de context.

2. Een andere manier om hetzelfde te doen, zelfs door nog minder code te schrijven.

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

Waarschijnlijkgebruikt ooit dezelfde bindmethode

De setTimeout neemt alleen de locatie van de functie en de functie heeft al de context? Hoe dan ook, het werkt!

OPMERKING: deze werken met elke functie die u in js gebruikt.


Antwoord 7, autoriteit 2%

Uw codebereik (this)wordt uw window-object, niet uw reactiecomponent, en daarom setTimeout(this.setState({position: 1}), 3000)zal op deze manier crashen.

Dat komt van javascript, niet van React, het is js-afsluiting


Dus, om uw huidige reactiecomponentbereik te binden, doet u dit:

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

Of als uw browser es6 ondersteunt of uw projs ondersteuning heeft om es6 naar es5 te compileren, probeer dan ook de pijlfunctie, aangezien pijlfunctie is om ‘dit’ probleem op te lossen:

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

Antwoord 8

Er zijn drie manieren om toegang te krijgen tot het bereik binnen de functie ‘setTimeout’

Eerst,

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

Ten tweede is om de ES6-pijlfunctie te gebruiken, omdat de pijlfunctie zelf geen bereik had (dit)

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

De derde is om het bereik binnen de functie te binden

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

Antwoord 9

Geef de functie gewoon door als referentie, het is niet nodig om deze in een anonieme functie te verpakken of zelfs te binden, wat weer een andere functie creëert.

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

Voer setTimeout

in

Het lijkt erop dat mensen zich niet realiseren dat setTimeouten setIntervalfeitelijk optionele onbeperkte parametersaccepteren.

setTimeout(callback, timeout?, param1?, param2?, ...)

De reden is om het terugbellen eenvoudiger te maken, dus in plaats van dit

setTimeout(
  function(){
    this.doSomething(true, "string", someVariable)
  }.bind(this),
  500
)

Je kunt dit schrijven

setTimeout(this.doSomething, 500, true, "string", someVariable)

Is dat niet mooi en elegant?


Bug?

Er is geen bug in React die setTimeout direct aanroept, dus als je er niet door in de war was, overweeg dan dit.

function doSomething() {/* */}
const a = doSomething() // immediately invokes and assigns a result
const b = doSomething   // stores a reference for later call
// call later
const x = a() // error
const y = b() // invokes doSomething and assigns a result

En in jouw geval met setStateis dit in principe hetzelfde.
Wanneer u uw setTimeout-callback registreert, roept u deze per ongeluk onmiddellijk aan, waar u in plaats daarvan een verwijzing naar moet doorgeven.

function doSomething() {/* */}
// wrong
setTimeout(doSomething(), 500) // This is basically the same as writing the `a` from above
setTimeout(a, 500)             // like this. See the problem? a() cannot be called later.

Je hebt drie opties om het op te lossen.

  1. een referentie doorgeven
setTimeout(this.doSomething, 500)
  1. omhul een anonieme pijlfunctie die transparant is voor this,
    wat betekent dat het de buitenste (ouder) thisvastlegt.
    merk op dat dit je functie elke keer dat je dit aanroept in een andere functie verpakt
setTimeout(() => this.doSomething(), 500)
  1. omhul een standaard anonieme functie, maar aangezien deze een eigen thisheeft, moet je deze binden aan de thisvan de ouder.
    merk op dat dit uw functie in een andere functie verpakt EN DAN bindt, waardoor elke keer een derde functie wordt gemaakt
setTimeout(function(){this.doSomething()}.bind(this), 500)

Antwoord 10

Je hebt een syntaxdeclaratiefout gemaakt, gebruik de juiste setTimeout-declaratie

message:() => { 
  setTimeout(() => {this.setState({opened:false})},3000); 
  return 'Thanks for your time, have a nice day 😊! 
}

Antwoord 11

Probeer de ES6-syntaxis van de ingestelde time-out te gebruiken. Normale javascript setTimeout() werkt niet in react js

setTimeout(
      () => this.setState({ position: 100 }), 
      5000
    );
Previous articleDeling in C++
Next articleWat doet ‘set -x’?

Other episodes