setState 안전하게!

yhko1992·2022년 2월 1일
0

REACT JS - BASIC

목록 보기
3/26


<본 사진은 state와 관련이 1정도 있습니다>

state를 update할때 어떻게 해야 안전하면서 효율적으로 업뎃이 가능한지 배웠다.

배운점

  1. setState할때 state가 바뀐 컴포넌트만 리랜더링 된다. 그리고 리랜더링 될때 state가 적용되는 부분만 국소적으로 리랜더링 된다.

    • 그래서 주사위가 이전과 같은 주사위가(이전과 같은 state) 뽑혔을 경우 랜더링 되지 않고 가만히 있는 경우를 볼 수 있다?
    • 아니다 setState가 실행되면 무조건 render 메소드가 실행된다.
    • 그리고 setState가 여러번 실행되면 한꺼번에 모아놨다가 한번에 실행한다. 성능개선을 위해서! 따라서 setState가 연속실행되면 여러번 업데이트하는게 아니라 한번만 업데이트 된다.
    this.setState({ score: this.state.score + 1 });
    this.setState({ score: this.state.score + 1 });
    this.setState({ score: this.state.score + 1 });
    // 그럼 리액트는 자동적으로 마지막것이 가장 최신이며 최종 결과물이라 생각하고 마지막 setState만 비동기 실행을 할 것이다. 그래서 요런 경우는 obj가 아닌 callBack 함수를 넘겨준다.
    this.setState(curState => ({ score: curState.score + 1 }));

    하지만 아래것이 나중에 테스팅할때 더 좋은 포맷이다. 따로 함수로 빼뒀다가 pass하는게 좋다.

    increamentByOne(curSt) {
      return {score:curSt.score+1}
    }
    this.setState(this.increamentByOne);
  2. 그리고 state 업데이트 할때 state안에 있는 값을 직접적으로 alter하려 하지 말고 copy를 만든다음 업데이트 해라.

    • 직접 변경하면 나중에 디버깅할때 고통스러워진다. map, filter, spread 같은걸로 copy를 만들어라.
    • brandNew version should be updated into this.state
  3. 변경될 필요가 없는 변수는 state에 저장하지 말것. state는 최대한 간결한게 좋다.

  4. inline으로 스타일을 변경하고 싶을때는 jsx element에 style attribute를 추가하고 obj를 pass 해주면 된다.

    • 그치만 역시나 추천하지는 않는다!
const divStyle = {
  color: 'blue',
  backgroundImage: 'url(' + imgUrl + ')',
};

function HelloWorldComponent() {
  return <div style={divStyle}>Hello World!</div>;
}
  1. 여러가지 데이터를 props로 넘기려고 할떄는 obj에 담아서 넘기는게 깔끔하다
const coins = [
  { side: 'heads', imgSrc: 'https://www' },
  { side: 'tails', imgSrc: 'https://www' },
];
  1. && 나 ternary operator를 사용해서 깔끔하게 로직을 처리하자
this.setState(st => {
   return {
      ...,
      nHeads:st.nHeads + (newCoin.side === 'heads' ? 1 : 0),
      nTails:st.nTails + (newCoin.side === 'tails' ? 1 : 0)
   }
})

{this.state.sides && <Coin />}
  1. 기존에 state에 저장되었던것과 다른 색깔이 나올때 까지 반복하다가 다른색깔이 나오면 setState하기!

    • do/while 구문 사용해보기
    let newColor;
    do {
      newColor = choice(this.props.allColors);
    } while (this.state.color === newColor);
    
    this.setState({ color: newColor });
  2. bind는 즉시 하지 않고 constructor에 하는게 안전하다

    • 왜냐면 event에다가 bind하면 이벤트가 발생할때마다 새로운 함수가 생성될거고 그럼 성능에 문제가 생길 수 있다.
    • arrow function을 사용할때도 마찬가지. 이벤트 발생할때마다 새로운 함수가 발생할 거다.
    // bad
    <div className="blah" onMouseEnter={this.mouseHandle.bind(this)} />

질문!

  • 부모 setState가 실행되고 자식 setState가 실행될시 자식스테이트에서 rendering이 일어나지 않는다. 부모의 setState가 실행되면 당연히 자식이 랜더링 될것이기 때문에 두번 랜더링하지않고 말그대로 state만 바꾸는 것인가?

  • 그리고 이때 업데이트된 todos를 가지고 Todo 컴포넌트를 부모에서 다시 랜더링해서 DOM을 구성할텐데 그때 특정 자식 컴포넌트의 이전 state가 날라가지 않고 그대로 남아있는가?

    • 그런거 같은데?? 근데, 부모에서 랜더링 할때 이미 자식내부에서 setState되어서 업데이트된 state를 참고해서 랜더링하는 거 같다. 그렇지 않으면 자식내부에서 또다시 setState되서 랜더링 되야하는데 자식내부의 setState에서는 랜더링 되지 않는다. 그말은 부모에서 랜더링 될때 이미 자식내부에 state가 바뀌었고 부모는 그걸 알고있다는 뜻인가?
profile
'과연 이게 최선일까?' 끊임없이 생각하기

0개의 댓글