由于 componentDidUpdate 方法中的 setState 导致无限循环?

我有一个简单的发现不同颜色的应用程序。游戏的重点只是从集合中选择不同的颜色。在 5 个点之后,该集合呈现为 3x3 而不是 2x2。但我遇到了这个错误


“未捕获的不变违规:超过最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 内重复调用 setState 时,可能会发生这种情况。React 限制嵌套更新的数量以防止无限循环。在不变”


我试图将它上传到codepen,但由于无限循环,一旦遇到错误,它似乎就会杀死应用程序。我阅读了这个问题,他们说 componentDidUpdate 中的 setState 可能会导致另一个更新,然后 inf 循环,但我不确定我是如何导致这个问题的。


componentDidUpdate() {

        if (this.state.score === 4) {

            this.setState({ size: 9 });

        } else if (this.state.score === 9) {

            this.setState({ size: 16 });

        }

    }


四季花海
浏览 248回答 2
2回答

哔哔one

您可以在增加分数后立即进行检查:if (counter < 2) {&nbsp; console.log("CORRECT!");&nbsp; this.increment();&nbsp; this.upgrade();&nbsp; this.pickColorPair();&nbsp; this.loadColor();}升级功能:&nbsp; upgrade() {&nbsp; &nbsp; if (this.state.score === 4) {&nbsp; &nbsp; &nbsp; this.setState({&nbsp; &nbsp; &nbsp; &nbsp; size: 9&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; } else if (this.state.score === 9) {&nbsp; &nbsp; &nbsp; this.setState({&nbsp; &nbsp; &nbsp; &nbsp; size: 16&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }&nbsp; }在构造函数中绑定它:this.upgrade = this.upgrade.bind(this);class ColorGame extends React.Component {&nbsp; constructor(props) {&nbsp; &nbsp; super(props);&nbsp; &nbsp; this.colorSet = [&nbsp; &nbsp; &nbsp; ['blue', '#EA401B'],&nbsp; &nbsp; &nbsp; ['yellow', '#34AD44'],&nbsp; &nbsp; &nbsp; ['green', '#80279D'],&nbsp; &nbsp; &nbsp; ['pink', 'purple']&nbsp; &nbsp; ];&nbsp; &nbsp; this.pickColorPair = this.pickColorPair.bind(this);&nbsp; &nbsp; this.loadColor = this.loadColor.bind(this);&nbsp; &nbsp; this.randomize = this.randomize.bind(this);&nbsp; &nbsp; this.isMatch = this.isMatch.bind(this);&nbsp; &nbsp; this.increment = this.increment.bind(this);&nbsp; &nbsp; this.upgrade = this.upgrade.bind(this);&nbsp; &nbsp; this.state = {&nbsp; &nbsp; &nbsp; colors: [],&nbsp; &nbsp; &nbsp; score: 0,&nbsp; &nbsp; &nbsp; colorPair: [],&nbsp; &nbsp; &nbsp; size: 4&nbsp; &nbsp; }&nbsp; }&nbsp; pickColorPair() {&nbsp; &nbsp; const randomNumber = Math.floor(Math.random() * 4);&nbsp; &nbsp; this.setState({&nbsp; &nbsp; &nbsp; colorPair: this.colorSet[randomNumber]&nbsp; &nbsp; }, () => {&nbsp; &nbsp; &nbsp; this.loadColor()&nbsp; &nbsp; });&nbsp; }&nbsp; loadColor() {&nbsp; &nbsp; // console.log(this.state.colorPair);&nbsp; &nbsp; let colorArray = [this.state.colorPair[0]];&nbsp; &nbsp; for (let i = 1; i < this.state.size; i++) {&nbsp; &nbsp; &nbsp; colorArray.push(this.state.colorPair[1]);&nbsp; &nbsp; }&nbsp; &nbsp; this.randomize(colorArray);&nbsp; &nbsp; this.setState(() => ({&nbsp; &nbsp; &nbsp; colors: colorArray&nbsp; &nbsp; }));&nbsp; }&nbsp; randomize(colorArray) {&nbsp; &nbsp; for (let i = colorArray.length - 1; i > 0; i--) {&nbsp; &nbsp; &nbsp; let j = Math.floor(Math.random() * (i + 1)); // random index from 0 to i&nbsp; &nbsp; &nbsp; // swap elements array[i] and array[j]&nbsp; &nbsp; &nbsp; // we use "destructuring assignment" syntax to achieve that&nbsp; &nbsp; &nbsp; // you'll find more details about that syntax in later chapters&nbsp; &nbsp; &nbsp; // same can be written as:&nbsp; &nbsp; &nbsp; // let t = colorArray[i]; colorArray[i] = colorArray[j]; colorArray[j] = t&nbsp; &nbsp; &nbsp; [colorArray[i], colorArray[j]] = [colorArray[j], colorArray[i]];&nbsp; &nbsp; }&nbsp; &nbsp; return (colorArray);&nbsp; }&nbsp; isMatch(color) {&nbsp; &nbsp; let counter = 0;&nbsp; &nbsp; //We only need to compare the first 3 to know if we got the right answer&nbsp; &nbsp; for (let i = 0; i < 3; i++) {&nbsp; &nbsp; &nbsp; if (color === this.state.colors[i]) {&nbsp; &nbsp; &nbsp; &nbsp; counter++;&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; if (counter < 2) {&nbsp; &nbsp; &nbsp; console.log("CORRECT!");&nbsp; &nbsp; &nbsp; this.increment();&nbsp; &nbsp; &nbsp; this.upgrade();&nbsp; &nbsp; &nbsp; this.pickColorPair();&nbsp; &nbsp; &nbsp; this.loadColor();&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; console.log("INCORRECT GUESS!");&nbsp; &nbsp; }&nbsp; }&nbsp; increment() {&nbsp; &nbsp; this.setState((prevState) => ({&nbsp; &nbsp; &nbsp; score: prevState.score + 1&nbsp; &nbsp; }));&nbsp; &nbsp; console.log(this.state.score);&nbsp; }&nbsp; upgrade() {&nbsp; &nbsp; if (this.state.score === 4) {&nbsp; &nbsp; &nbsp; this.setState({&nbsp; &nbsp; &nbsp; &nbsp; size: 9&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; } else if (this.state.score === 9) {&nbsp; &nbsp; &nbsp; this.setState({&nbsp; &nbsp; &nbsp; &nbsp; size: 16&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }&nbsp; }&nbsp; render() {&nbsp; &nbsp; return ( <&nbsp; &nbsp; &nbsp; div className = "container" >&nbsp; &nbsp; &nbsp; <&nbsp; &nbsp; &nbsp; h1 > Spot The Difference < /h1> <&nbsp; &nbsp; &nbsp; h2 > Score: {&nbsp; &nbsp; &nbsp; &nbsp; this.state.score&nbsp; &nbsp; &nbsp; } < /h2> <&nbsp; &nbsp; &nbsp; h2 > Size: {&nbsp; &nbsp; &nbsp; &nbsp; this.state.size&nbsp; &nbsp; &nbsp; } < /h2> <&nbsp; &nbsp; &nbsp; button className = 'startbtn'&nbsp; &nbsp; &nbsp; onClick = {&nbsp; &nbsp; &nbsp; &nbsp; this.pickColorPair&nbsp; &nbsp; &nbsp; } > Start < /button> <&nbsp; &nbsp; &nbsp; GameBoard colors = {&nbsp; &nbsp; &nbsp; &nbsp; this.state.colors&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; isMatch = {&nbsp; &nbsp; &nbsp; &nbsp; this.isMatch&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; score = {&nbsp; &nbsp; &nbsp; &nbsp; this.state.score&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; /> <&nbsp; &nbsp; &nbsp; /div>&nbsp; &nbsp; );&nbsp; };}const GameBoard = (props) => ( <&nbsp; div className = "gameboard" > {&nbsp; &nbsp; props.colors.map((color, index) => ( <&nbsp; &nbsp; &nbsp; ColorCircle key = {&nbsp; &nbsp; &nbsp; &nbsp; index&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; color = {&nbsp; &nbsp; &nbsp; &nbsp; color&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; isMatch = {&nbsp; &nbsp; &nbsp; &nbsp; props.isMatch&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; score = {&nbsp; &nbsp; &nbsp; &nbsp; props.score&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; />&nbsp; &nbsp; ))&nbsp; } <&nbsp; /div>)class ColorCircle extends React.Component {&nbsp; constructor(props) {&nbsp; &nbsp; super(props);&nbsp; &nbsp; this.isMatch = this.isMatch.bind(this);&nbsp; &nbsp; this.levelMode = this.levelMode.bind(this);&nbsp; }&nbsp; levelMode() {&nbsp; &nbsp; console.log(this.props.score)&nbsp; &nbsp; if (this.props.score < 5) {&nbsp; &nbsp; &nbsp; return 'colorCircle-level1';&nbsp; &nbsp; } else if (this.props.score > 9) {&nbsp; &nbsp; &nbsp; return 'colorCircle-level3';&nbsp; &nbsp; } else if (this.props.score >= 4) {&nbsp; &nbsp; &nbsp; return 'colorCircle-level2';&nbsp; &nbsp; }&nbsp; }&nbsp; isMatch() {&nbsp; &nbsp; this.props.isMatch(this.props.color);&nbsp; }&nbsp; render() {&nbsp; &nbsp; return ( <&nbsp; &nbsp; &nbsp; div >&nbsp; &nbsp; &nbsp; <&nbsp; &nbsp; &nbsp; button className = {&nbsp; &nbsp; &nbsp; &nbsp; this.levelMode()&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; onClick = {&nbsp; &nbsp; &nbsp; &nbsp; this.isMatch&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; style = {&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; backgroundColor: this.props.color&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; } > < /button> <&nbsp; &nbsp; &nbsp; /div >&nbsp; &nbsp; )&nbsp; }}//we can pass in props to the main app through here. {} is the JSX brackets, not an object literalReactDOM.render( < ColorGame / > , document.getElementById('app'));* {&nbsp; box-sizing: border-box;&nbsp; margin: 0;&nbsp; padding: 0;}button {&nbsp; width: 50px;&nbsp; height: 50px;&nbsp; border-radius: 50%;&nbsp; outline: none;&nbsp; border: none;}#app {&nbsp; display: block;&nbsp; margin: auto;&nbsp; width: 800px;&nbsp; text-align: center;}.container {&nbsp; width: 60rem;&nbsp; height: 70rem;&nbsp; background-color: #004d66;&nbsp; margin: auto;}.gameboard {&nbsp; display: flex;&nbsp; flex-wrap: wrap;&nbsp; margin: auto;&nbsp; width: 30rem;&nbsp; // background: white;}.startbtn {&nbsp; margin: 3rem 0 5rem 0;&nbsp; width: 8rem;&nbsp; height: 8rem;}.colorCircle-level1 {&nbsp; width: 15rem;&nbsp; height: 15rem;}.colorCircle-level2 {&nbsp; width: 10rem;&nbsp; height: 10rem;}.colorCircle-level3 {&nbsp; width: 7rem;&nbsp; height: 7rem;}//Spacing$s-size: 1.2rem;$m-size: 1.6rem;$l-size: 3.2rem;$xl-size: 4.8rem;$desktop-breakpoint: 45rem;// rem (better support for accessibility)html {&nbsp; //makes rem = 10px&nbsp; font-size: 62.5%;}body {&nbsp; font-family: Helvetica, Arial, san-serif;&nbsp; //now rem is 16px&nbsp; font-size: $m-size;&nbsp; background-color: #203c589a;&nbsp; color: white;}button {&nbsp; cursor: pointer;}button:disabled {&nbsp; cursor: default;}<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script><!DOCTYPE html><html><head>&nbsp; <meta charset="UTF-8">&nbsp; <meta name="viewport" content="width=device-width, initial-scale=1.0">&nbsp; <link rel="shortcut icon" href="~/favicon.ico">&nbsp; <title>Spot The Difference</title></head><body>&nbsp; <div id="app"></div>&nbsp; <script src="/bundle.js"></script></body></html>

泛舟湖上清波郎朗

评论中的答案。将代码移动到 isMatch 中或将其保留在 componentDidUpdate 中,但还要调整代码以检查 prevState
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript