简体   繁体   English

警告:setState(…):只能更新已安装或正在安装的组件。 这通常意味着

[英]Warning: setState(…): Can only update a mounted or mounting component. This usually means

I am working on an exercise in the Udemy Advanced Webdeveloper Bootcamp. 我正在Udemy Advanced Webdeveloper训练营中进行练习。 The exercise asked to come up with a page of 32 boxes that randomly change colour (every x seconds). 练习要求拿出一个由32个方框组成的页面,它们随机改变颜色(每x秒)。 My solution is not exactly that. 我的解决方案不完全是这样。 I change the color of all 32 boxes at the same time. 我同时更改所有32个框的颜色。 It almost works. 它几乎可以工作。 I get random 32 boxes initially, but does not change the color later. 我最初会随机得到32个盒子,但以后不会更改颜色。 My console tells me I am doing something wrong with the setState. 我的控制台告诉我setState做错了。 But I cannot figure out what. 但我不知道是什么。 I think my changeColor is a pure function: 我认为我的changeColor是一个纯函数:

import React, { Component } from 'react';
import './App.css';

class Box extends Component {
    render() {

        var divStyle = {
            backgroundColor: this.props.color
        }

        return(
            <div className="box" style={divStyle}></div>
        );
    }
}

class BoxRow extends Component {
    render() {
        const numOfBoxesInRow = 8;
        const boxes = [];

        for(var i=0; i < numOfBoxesInRow; i++) {
            boxes.push(<Box color={this.props.colors[i]} key={i+1}/>);
        }

        return(
            <div className="boxesWrapper">
            {boxes}
            </div>
            );
    }
}

class BoxTable extends Component {

    constructor(props) {
        super(props);
        this.getRandom = this.getRandom.bind(this);
        this.changeColors = this.changeColors.bind(this);
        this.state = {
            randomColors: this.getRandom(this.props.allColors, 32) // hardcoding
        };

        this.changeColors();
    }

    changeColors() {
        setInterval(
            this.setState({randomColors: this.getRandom(this.props.allColors, 32)}), 5000);
    }

    getRandom(arr, n) {
        var result = new Array(n),
            len = arr.length,
            taken = new Array(len);
        if (n > len)
            throw new RangeError("getRandom: more elements taken than available");
        while (n--) {
            var x = Math.floor(Math.random() * len);
            result[n] = arr[x in taken ? taken[x] : x];
            taken[x] = --len in taken ? taken[len] : len;
        }
        return result;
    }

    render () {
        const numOfRows = 4;
        const rows = [];

        for(let i=0; i < numOfRows; i++) {
          rows.push(
              <BoxRow colors={this.state.randomColors.slice(8*i,8*(1+i))} key={i+1}/>
            )
        }

        return (
          <div className="rowsWrapper">
          {rows}
          </div>
        );
    }
}

BoxTable.defaultProps = {
    allColors: ["AliceBlue","AntiqueWhite","Aqua","Aquamarine","Azure","Beige",
    "Bisque","Black","BlanchedAlmond","Blue","BlueViolet","Brown","BurlyWood",
    "CadetBlue","Chartreuse","Chocolate","Coral","CornflowerBlue","Cornsilk",
    "Crimson","Cyan","DarkBlue","DarkCyan","DarkGoldenRod","DarkGray","DarkGrey",
    "DarkGreen","DarkKhaki","DarkMagenta","DarkOliveGreen","Darkorange",
    "DarkOrchid","DarkRed","DarkSalmon","DarkSeaGreen","DarkSlateBlue",
    "DarkSlateGray","DarkSlateGrey","DarkTurquoise","DarkViolet","DeepPink",
    "DeepSkyBlue","DimGray","DimGrey","DodgerBlue","FireBrick","FloralWhite",
    "ForestGreen","Fuchsia","Gainsboro","GhostWhite","Gold","GoldenRod","Gray",
    "Grey","Green","GreenYellow","HoneyDew","HotPink","IndianRed","Indigo",
    "Ivory","Khaki","Lavender","LavenderBlush","LawnGreen","LemonChiffon",
    "LightBlue","LightCoral","LightCyan","LightGoldenRodYellow","LightGray",
    "LightGrey","LightGreen","LightPink","LightSalmon","LightSeaGreen",
    "LightSkyBlue","LightSlateGray","LightSlateGrey","LightSteelBlue",
    "LightYellow","Lime","LimeGreen","Linen","Magenta","Maroon",
    "MediumAquaMarine","MediumBlue","MediumOrchid","MediumPurple",
    "MediumSeaGreen","MediumSlateBlue","MediumSpringGreen","MediumTurquoise",
    "MediumVioletRed","MidnightBlue","MintCream","MistyRose","Moccasin",
    "NavajoWhite","Navy","OldLace","Olive","OliveDrab","Orange","OrangeRed",
    "Orchid","PaleGoldenRod","PaleGreen","PaleTurquoise","PaleVioletRed",
    "PapayaWhip","PeachPuff","Peru","Pink","Plum","PowderBlue","Purple",
    "Red","RosyBrown","RoyalBlue","SaddleBrown","Salmon","SandyBrown",
    "SeaGreen","SeaShell","Sienna","Silver","SkyBlue","SlateBlue","SlateGray",
    "SlateGrey","Snow","SpringGreen","SteelBlue","Tan","Teal","Thistle",
    "Tomato","Turquoise","Violet","Wheat","White","WhiteSmoke","Yellow","YellowGreen"]
}

export default BoxTable

You need to use a lambda function in order to use setState inside setInterval 您需要使用lambda函数才能在setInterval中使用setState

setInterval(() => {
        this.setState({randomColors: this.getRandom(this.props.allColors, 
                       32)});
                  }, 5000)

try to change your changeColors function to like this: 尝试将您的changeColors函数更改为这样:

changeColors() {
        setInterval(() => this.setState({randomColors: this.getRandom(this.props.allColors, 32)}), 5000);
    }

the first param of setInterval is function, in your original code you already executed this setState and didn't passed the function itself setInterval的第一个参数是function,在您的原始代码中,您已经执行了setState并且没有传递函数本身

You will need to update the state after the component creation phase, inside componentDidMount() 在组件创建阶段之后,您将需要在componentDidMount()内部更新状态。

class BoxTable extends Component {

    constructor(props) {
        super(props);
        this.getRandom = this.getRandom.bind(this);
        this.changeColors = this.changeColors.bind(this);
        this.state = {
            randomColors: this.getRandom(this.props.allColors, 32) // hardcoding
        };

        // delete this line 
        //this.changeColors();
    }
    // replace changeColors by componentDidMount, 
    // this function will be called automatically by react
    componentDidMount() {
        setInterval(
            this.setState({randomColors: this.getRandom(this.props.allColors, 32)}), 5000);
    }

    getRandom(arr, n) {
        var result = new Array(n),
            len = arr.length,
            taken = new Array(len);
        if (n > len)
            throw new RangeError("getRandom: more elements taken than available");
        while (n--) {
            var x = Math.floor(Math.random() * len);
            result[n] = arr[x in taken ? taken[x] : x];
            taken[x] = --len in taken ? taken[len] : len;
        }
        return result;
    }

    render () {
        const numOfRows = 4;
        const rows = [];

        for(let i=0; i < numOfRows; i++) {
          rows.push(
              <BoxRow colors={this.state.randomColors.slice(8*i,8*(1+i))} key={i+1}/>
            )
        }

        return (
          <div className="rowsWrapper">
          {rows}
          </div>
        );
    }
}

You are calling this.setState before the component has mounted (from the constructor). 您正在(从构造函数中)安装组件之前调用this.setState Try instead making your first this.ChangeColors from the componentDidMount lifecycle function. 尝试改用componentDidMount生命周期函数中的第一个this.ChangeColors

Additionally, it's not a bad idea to clear the interval when it unmounts in componentWillUnMount 此外,清除在componentWillUnMount卸载的间隔并不是一个坏主意

Edit: By changing the interval to call after the first wait you do prevent the error, for now . 编辑:通过改变间隔来叫你做的第一等待防止错误之后, 现在 I'd recommend using the lifecycle functions to build good habits. 我建议使用生命周期功能来养成良好的习惯。 It's just a temporary assignment, but in a full project you'd be putting yourself at risk to break the component again later by making it possible to call this.setState before it is reliably mounted. 这只是一个临时任务,但是在一个完整的项目中,您可能会this.setState在稍后再次破坏该组件,方法是可以在可靠安装之前调用this.setState

暂无
暂无

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

相关问题 只能更新已安装或安装的组件。 这通常意味着您在已卸载的组件上调用了setState() - Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component setState(...):只能更新已安装或安装的组件。 这通常意味着您在已卸载的组件上调用了setState()。 这是一个无操作 - setState(…): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op 尝试在其他类中重用组件并获取错误:“警告:setState(...):只能更新已安装或安装的组件。 ” - Trying to re-use component in other class and getting error: “Warning: setState(…): Can only update a mounted or mounting > component. ” 只能更新已安装或正在安装的组件。 - Can only update a mounted or mounting component. 反应警告:setState(…)只能更新已安装或正在安装的组件 - React Warning: setState(…) Can only update a mounted or mounting component 警告:setState(…):只能更新已安装或正在安装的组件 - Warning react : setState(…): Can only update a mounted or mounting component 警告:setState(…):只能更新已安装或正在安装的组件,如何卸载? - Warning: setState(…): Can only update a mounted or mounting component, How to unmount? 警告:setState(...):只能更新已安装或安装的组件 - Warning: setState(…): Can only update a mounted or mounting component 反应警告setState(…):只能更新已安装或正在安装的组件 - React warning setState(…): Can only update a mounted or mounting component setState只能更新已安装或安装的组件 - setState Can only update a mounted or mounting component
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM