简体   繁体   English

ReactJS中的setState

[英]setState in ReactJS

I'm new to ReactJS and I can't seem to find out why the result of the following setState is not as I expect it to be (ie to increment the value every second by 1) 我是ReactJS的新手,我似乎无法找出为什么以下setState的结果不符合我的预期(即,将值每秒增加1)

import React from 'react';
import ReactDOM from 'react-dom';

class Layout extends React.Component {

    constructor() {
        super();
        this.state = {
            name: "Behnam",
            i: 0
        }
    }

    render() {

        setInterval(() => {
            this.setState({ name : "Behnam" + this.state.i });
            this.setState({ i: this.state.i + 1 });
        }, 1000);

        return (
            <div className="container">
                {this.state.name}
            </div>
        );
    }
}

ReactDOM.render(<Layout />, document.getElementById('app'));

Instead the output string rapidly increases (I guess as fast as react is trying to keep its' virtual DOM updated). 取而代之的是,输出字符串迅速增加(我猜想与react试图保持其虚拟DOM更新一样快)。 So I was wondering what is the right way to do this? 所以我想知道什么是正确的方法?

Every time you change the state, you rerender the component. 每次更改状态时,都会重新渲染组件。 Because you initiated the setInterval in the render method, you get another interval, which changes the state, and rerenders, and so on. 因为您是在render方法中启动setInterval ,所以您会得到另一个间隔,该间隔会更改状态并重新渲染,依此类推。

Move the setInterval to componentDidMount , which is invoked only once, when the component mounts: setInterval移至componentDidMount ,组件安装时仅调用一次:

import React from 'react';
import ReactDOM from 'react-dom';

class Layout extends React.Component {

    constructor() {
        super();
        this.state = {
            name: "Behnam",
            i: 0
        }
    }

    componentDidMount() { set the interval after the component mounted, and save the reference
        this.interval = setInterval(() => {
            this.setState({ 
                name: `Behnam${this.state.i}`, 
                i: this.state.i + 1
            });
        }, 1000);
    }

    componentWillUnmount() {
        this.interval && clearInterval(this.interval); // clear the interval when the component unmounts
    } 

    render() {
        return (
            <div className="container">
                {this.state.name}
            </div>
        );
    }
}

ReactDOM.render(<Layout />, document.getElementById('app'));

Currently, it is creating an interval every time the component is rendered, so there are multiple timers incrementing the value. 当前, 每次渲染组件时都会创建一个间隔,因此有多个计时器递增该值。 You probably want to do it in componentDidMount() instead of render() . 您可能想要在componentDidMount()而不是render() See docs . 参见docs

import React from 'react';
import ReactDOM from 'react-dom';

class Layout extends React.Component {

    constructor() {
        super();
        this.state = {
            name: "Behnam",
            i: 0
        }
    }

    componentDidMount() {
        setInterval(() => {
            this.setState({ name : "Behnam" + this.state.i });
            this.setState({ i: this.state.i + 1 });
        }, 1000);
    }

    render() {
        return (
            <div className="container">
                {this.state.name}
            </div>
        );
    }
}

ReactDOM.render(<Layout />, document.getElementById('app'));

Every time a render is triggered, you're calling setInterval again, adding to the number of active intervals on the page. 每次触发渲染时,您都会再次调用setInterval ,从而增加页面上的活动间隔数。

You should perhaps make use of another lifecycle method, such as componentDidMount . 您也许应该使用其他生命周期方法,例如componentDidMount You should remember to save the interval ID returned by setInterval , so that you can call clearInterval in componentWillUnmount . 您应该记住保存setInterval返回的间隔ID,以便可以在componentWillUnmount调用clearInterval

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM