Nhat
Nhat

Reputation: 409

Why does this.setState work in my case

I am just trying to create a very simple app which I will enter a number and the computer will generate boxes with that number and change color of one box at a time randomly. the code works but I don't understand why it works, at the randomBlinking function I just need to have this.setState({}) or more strange, I could just but anything in the state to this.setState({}) and the code will work the same, it will change color of a random box every 1 second. I cut down I app to only the part that I don't understand, could someone please help me answer this question.

import React from 'react';
import CubeRender from '../therapeuticEffect/CubeRender';
import '../therapeuticEffect/style.css';

class TherapeuticEffect extends React.Component {
constructor(props) {
    super(props)
    this.state = {
        cubeArray: [],
        cubeNumber: 0,
        cubeSize: 100,
    }
    this.blinking = null;
}

onNumberChange = (event) => {
    this.setState({ [event.target.name]: event.target.value })
}

onFormSubmit = (event) => {
    event.preventDefault();
    clearInterval(this.blinking);
    this.cubeArrayRender();
}

cubeArrayRender = () => {
    let { cubeNumber } = this.state;

    let cubes = parseInt(cubeNumber, 10);

    let array = cubes ? Array(cubes).fill() : [];
    let cubeArray = array.length === 0 ? [] : array.map((c) => (this.randomColor()));
    this.setState({ cubeArray })
    this.randomBlinking();
}

randomBlinking = () => {
    this.blinking = setInterval(() => {
        const array = this.state.cubeArray;
            const randIndex = Math.floor(Math.random() * array.length);
            array[randIndex] = this.randomColor();

            //HOW COULD THIS WORK

            this.setState({})
    }, 500);
}

randomColor = () => {
    let r = Math.floor(Math.random() * 256);
    let g = Math.floor(Math.random() * 256);
    let b = Math.floor(Math.random() * 256);
    let color = `rgb(${r}, ${g}, ${b})`
    return color;
}

render() {
    const { cubeArray, cubeNumber, cubeSize } = this.state
    return (
        <div>
            <form className='menu-bar' onSubmit={this.onFormSubmit}>
                <div>
                    <label>cube number </label>
                    <input type='number' name='cubeNumber' value={cubeNumber} onChange={this.onNumberChange} />
                </div>

            </form>

            <CubeRender
                cubeArray={cubeArray}
                cubeSize={cubeSize}
            />
        </div>
    )
}

}

Upvotes: 1

Views: 34

Answers (1)

Tholle
Tholle

Reputation: 112787

You are mutating your state directly by writing array[randIndex] = this.randomColor(). This alone, which is not recommended, will not re-render your component. When you then write this.setState({}); the component will re-render with the state that you just mutated.

You could instead create a copy of your cubeArray array and overwrite a random index with a random color and update your state with that.

randomBlinking = () => {
  this.blinking = setInterval(() => {
    this.setState(previousState => {
      const cubeArray = [...previousState.cubeArray];
      const randIndex = Math.floor(Math.random() * cubeArray.length);

      cubeArray[randIndex] = this.randomColor();

      return { cubeArray };
    });
  }, 500);
};

Upvotes: 2

Related Questions