rhanziy

react. 에러 Cannot update during an existing state transition ... 본문

React

react. 에러 Cannot update during an existing state transition ...

rhanziy 2022. 1. 29. 19:13

Warning: Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.

"현존하는 state의 변화중에는 업데이트 할수 없습니다 "('랜더'내에서와 같이) 랜더 methods는 props와 state를 가진 하나의 순수한 function 이어야 합니다."

Render 메서드 내부에 setState로 state를 변경하지 말라는 경고메세지이다.

Render 내부에서 state를 바꾸면 모든 컴포넌트가 다시 렌더링되므로 무한 루프가 발생한다.

 

 

생활코딩 리액트 강의를 듣고 간단한  CRUD를 복습하면서 마주하게된 경고메세지이다!!

debugger로 어떤 단계에서 오류가 나나 확인해봤더니

} else if(this.state.mode === 'delete'){
      if(window.confirm("really!?")){
        let _content = Array.from(this.state.contents);
        let i = 0;
        while(i < _content.length){
          if(this.state.selected_id ===_content[i].id){
            _content.splice(i,1);
            break;
          }
          i += 1;
        }
        alert('deleted!');
        this.setState({contents:_content, mode:'welcome'});
      }

delete 버튼을 구현하면서 삭제 성공 메세지를 띄우고 setState mode를 welcome으로 바꾸는 코드에서 발생했다.

 

클릭시 mode가 바뀌는 버튼을 Controls 컴포넌트로 만들고, 받아온 mode를 getContents() 함수 안에서 그에 맞는 처리를 하도록 코드를 짰는데 다른 버튼(create, update)들과 다르게 오류가 왜 뜨지!?!? 뜯어보았다.

>> create, update버튼은 각각 content 컴포넌트 내부의 onSubmit 함수 내에서 데이터를 처리한다!

else if(this.state.mode === 'update'){
  let _content = this.getReadContent();
  _article = <UpdateContent data={_content} onSubmit={function(id, name, desc){
    let upContents = Array.from(this.state.contents);
    let i = 0;
    while ( i < upContents.length){
      if( upContents[i].id === id  ){
        upContents[i] = { id:id, name:name, desc:desc }
        break;
      }
      i += 1;
    }
    this.setState({
      contents:upContents,
      mode:'read',
    })
  }.bind(this)}></UpdateContent>
}

 

but, delete는 따로 컴포넌트를 만들지 않았으니 렌더의 Controls 내부 props onChangeMode에 if문으로 동일한 코드를 실행시켰더니 에러메세지가 사라졌다.

<Controls onChangeMode={function(_mode){
  if(_mode === 'delete'){
    if(window.confirm("really!?")){
      let _content = Array.from(this.state.contents);
      let i = 0;
      while(i < _content.length){
        if(this.state.selected_id ===_content[i].id){
          _content.splice(i,1);
          break;
        }
        i += 1;
      }
      alert('deleted!');
      this.setState({contents:_content, mode:'welcome'});
    }
  } else {
    this.setState({mode:_mode});
  }
}.bind(this)}></Controls>

 

아래 라이브러리 저자의 solution
https://github.com/akveo/react-native-ui-kitten/issues/1094

say : 난 제한한다 / 모달의 컨텐츠를 분리시키는 것을 / 만약 그것이 분리된 하나의 state를 가지고 있다는걸 가정하면.
이것은 컴포넌트 랜더들의 총 양을 줄일 것이며, 이 이슈 자체를 스스로 고칠것이다.

(불만이 많이 달림 ㅎㅎ)

즉 모달 내부에서 리랜더링 시킬수 있는, 보통 setState 값을 가지는 부분을 모달 컴포넌트 외부에서 받지 말고, 그 영역만 따로 작게 함수형 등 컴포넌트를 만들어서 <모달> 여기 </모달> 모달 자식 쪽에서 리랜더링 시켜라 라는 뜻이다.

다시 말해 컴포넌트를 더 작게 분기시켜, <Modal visible={ 에 영향 주지 않도록 자식 부분에서 reRendering를 해라 라는 뜻.

 

출처:https://velog.io/@adguy/ReactJS-Warning-setState-Cannot-update-during-an-existing-state-transition

'React' 카테고리의 다른 글

react. css, useState, useEffect  (0) 2022.03.10
react. props  (0) 2022.03.10
react - State생성2  (0) 2022.03.08
react - State 생성  (0) 2022.03.08
react. JSX - Create Element  (0) 2022.03.07
Comments