Home > Mobile >  React render vs. UseState
React render vs. UseState

Time:06-26

I'm pretty new to this and can't really figure out how the render works - stuck with UseState for now :) -. Since I see a lot of people using it I wanted to ask for advice on what I'm doing wrong. Here are 2 examples one with UseState that works great and other with render that does nothing, I added some style so it looks kind of acceptable for anyone trying it out.

Any help appreciated, thank you

// USESTATE

    const [newColor, setNewColor] = useState('green');
    
      useEffect(() => {
        setBorder()
      }, [newColor])
    
      function setBorder() {
        if (newColor === 'green') {
          document.getElementById('green').style.borderColor = "orange";
          document.getElementById('yellow').style.borderColor = "black";
          document.getElementById('red').style.borderColor = "black";
      }
      if (newColor === 'yellow') {
          document.getElementById('yellow').style.borderColor = "orange";
          document.getElementById('green').style.borderColor = "black";
          document.getElementById('red').style.borderColor = "black";
      }
      if (newColor === 'red') {
          document.getElementById('red').style.borderColor = "orange";
          document.getElementById('green').style.borderColor = "black";
          document.getElementById('yellow').style.borderColor = "black";
      }
      }
    
      const changeBg = () => {
        document.body.style.backgroundColor = newColor;
      }
    
      return (
        <div>
        <div style={{width: '240px', height: '88px', border: '3px solid black', 'borderRadius': '10px'}}>
        <div id="green" onClick={(e) => setNewColor(e.target.id)}    style={{width: '40px', height: '40px', background: 'green', border: '3px solid black', float: 'left', margin: '20px 0 0 30px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
        <div id="yellow" onClick={(e) => setNewColor(e.target.id)}   style={{width: '40px', height: '40px', background: 'yellow', border: '3px solid black', float: 'left', margin: '20px 0 0 20px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
        <div id="red" onClick={(e) => setNewColor(e.target.id)}      style={{width: '40px', height: '40px', background: 'red', border: '3px solid black', float: 'left', margin: '20px 0 0 20px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
        </div>
        <button onClick={changeBg}>SAVE</button>
        </div>
      );

// RENDER

    class Test1 extends Component {
        constructor(props) {
            super(props);
            this.state = {
                newColor: 'green'
            }
        }
    
        componentDidUpdate() {
            if (this.newColor === 'green') {
                document.getElementById('green').style.borderColor = "orange";
                document.getElementById('yellow').style.borderColor = "black";
                document.getElementById('red').style.borderColor = "black";
            }
            if (this.newColor === 'yellow') {
                document.getElementById('yellow').style.borderColor = "orange";
                document.getElementById('green').style.borderColor = "black";
                document.getElementById('red').style.borderColor = "black";
            }
            if (this.newColor === 'red') {
                document.getElementById('red').style.borderColor = "orange";
                document.getElementById('green').style.borderColor = "black";
                document.getElementById('yellow').style.borderColor = "black";
            }
        }
    
        render() {
    
            const changeBg = () => {
                document.body.style.backgroundColor = this.newColor;
              }
    
    
            return (
                <div>
                <div style={{width: '240px', height: '88px', border: '3px solid black', 'borderRadius': '10px'}}>
                <div id="green" onClick={(e) => this.state={newColor: e.target.id}}    style={{width: '40px', height: '40px', background: 'green', border: '3px solid black', float: 'left', margin: '20px 0 0 30px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
                <div id="yellow" onClick={(e) => this.state={newColor: e.target.id}}   style={{width: '40px', height: '40px', background: 'yellow', border: '3px solid black', float: 'left', margin: '20px 0 0 20px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
                <div id="red" onClick={(e) => this.state={newColor: e.target.id}}      style={{width: '40px', height: '40px', background: 'red', border: '3px solid black', float: 'left', margin: '20px 0 0 20px', 'borderRadius': '10px', cursor: 'pointer'}}></div>
                </div>
                <button onClick={changeBg}>SAVE</button>
                </div>
              );
        }
    }

CodePudding user response:

First of all, you should never* update DOM directly in react as you do. In both of the examples you are doing that. The reason why second example doesn't work, componentDidUpdate is called when update happens (e.g. state change or props change), that doesn't happen because you aren't calling setState in second example; rather directly assigning to this.state. Also it should be this.state.newColor as noted in comments.

Idiomatic way to solve this in react is this:

export default function App() {
  const [newColor, setNewColor] = React.useState('green');

  const changeBg = () => {
    document.body.style.backgroundColor = newColor;
  };

  return (
    <div>
      <div
        style={{
          width: '240px',
          height: '88px',
          border: '3px solid black',
          borderRadius: '10px',
        }}
      >
        {['green', 'yellow', 'red'].map((x) => (
          <div
            onClick={(e) => setNewColor(x)}
            style={{
              width: '40px',
              height: '40px',
              background: x,
              border: '3px solid black',
              borderColor: newColor === x ? 'orange' : 'black',
              float: 'left',
              margin: '20px 0 0 30px',
              borderRadius: '10px',
              cursor: 'pointer',
            }}
          ></div>
        ))}
      </div>
      <button onClick={changeBg}>SAVE</button>
    </div>
  );
}

Although the boxes aren't well centered now, because you had different margin for first element, when all divs were written out by hand. But now I have same margin for all of them because I used a loop. I will leave it up to you to adjust it.


* Well in rare cases you can, when say integrating with 3rd party libraries, but in that case you should make sure react doesn't touch that part of the DOM.

  • Related