React 컴포넌트에서 this.setState를 여러 번 사용하면 어떻게 되나요?


102

this.setState를 여러 번 사용할 때 어떤 일이 발생하는지 확인하고 싶었습니다 (토론을 위해 두 번). 구성 요소가 두 번 렌더링 될 것이라고 생각했지만 분명히 한 번만 렌더링되었습니다. 내가 가진 또 다른 기대는 setState에 대한 두 번째 호출이 첫 번째 호출을 통해 실행될 수 있다는 것이지만 당신은 그것을 추측했습니다.

JSfiddle에 연결

var Hello = React.createClass({
  render: function() {
    return (
      <div>
        <div>Hello {this.props.name}</div>
        <CheckBox />
      </div>
    );
  }
});

var CheckBox = React.createClass({
  getInitialState: function() {
    return {
      alex: 0
    };
  },

  handleChange: function(event) {
    this.setState({
      value: event.target.value
    });
    this.setState({
      alex: 5
    });
  },

  render: function() {
    alert('render');
    return (
      <div>
        <label htmlFor="alex">Alex</label>
        <input type="checkbox" onChange={this.handleChange} name="alex" />
        <div>{this.state.alex}</div>
      </div>
    );
  }
});

ReactDOM.render(
  <Hello name="World" />,
  document.getElementById('container')
);

보시다시피 '렌더링'이라는 경고가 렌더링 할 때마다 팝업됩니다.

제대로 작동하는 이유에 대한 설명이 있습니까?


2
React는 매우 영리하며 렌더링에 필요한 상태가 변경 될 때만 다시 렌더링됩니다. 렌더 방법에서만 사용 this.state.alex하고 있습니다. 의존하는 요소를 추가하면 어떻게됩니까 this.state.value?
Martin Wedvich 2015

1
@MartinWedvich 내가 그것에 의존하는 경우 중단됩니다. 이를 위해 앱이 중단되지 않도록 기본값을 설정하는 'getInitialState'메소드가 있습니다.
alexunder

답변:


118

React는 이벤트 핸들러 및 수명주기 메서드에서 발생하는 상태 업데이트를 일괄 처리합니다. 따라서 <div onClick />핸들러 에서 상태를 여러 번 업데이트하면 React는 다시 렌더링하기 전에 이벤트 처리가 완료 될 때까지 기다립니다.

명확하게 말하면 이것은 React가 제어하는 ​​합성 이벤트 핸들러와 수명주기 메서드에서만 작동합니다. setTimeout예를 들어 상태 업데이트는 AJAX 및 이벤트 핸들러 에서 일괄 처리되지 않습니다 .


1
고마워요, 말이 되네요. 무대 뒤에서 어떻게되는지 아세요?
alexunder 2015

13
React는 합성 이벤트 핸들러 (예 :) <div onClick />및 구성 요소 수명주기 메서드를 완전히 제어하므로 setState일괄 상태 업데이트 호출 기간 동안의 동작을 안전하게 변경하고 플러시를 기다릴 수 있음을 알고 있습니다 . setTimeout대조적으로 AJAX 또는 핸들러에서 React는 핸들러 실행이 언제 완료되었는지 알 수 없습니다. 기술적으로 React는 두 경우 모두 상태 업데이트를 큐에 넣지 만 React가 제어하는 ​​핸들러 외부에서 즉시 플러시합니다.
크리스 고 드로

1
@neurosnap 나는 문서가 이것에 대해 자세히 설명하지 않는다고 생각합니다. State and Lifecycle 섹션setState 문서 에서 추상적으로 언급 됩니다. 현재 유일한 공식 배치 전략 인 ReactDefaultBatchingStrategy 의 코드를 참조하십시오 .
Chris Gaudreau 2017

2
@BenjaminToueg React 이벤트 핸들러 외부 ReactDOM.unstable_batchedUpdates(function)에서 일괄 처리 하는 데 사용할 수 있다고 생각합니다 setState. 이름에서 알 수 있듯이 보증이 무효화됩니다.
Chris Gaudreau 2017

1
항상이 사람을 참조하는 것이 좋습니다 twitter.com/dan_abramov/status/887963264335872000?lang=en
Hertzel Guinness

33

setState () 메서드는 구성 요소의 상태를 즉시 업데이트하지 않고 나중에 처리 할 수 ​​있도록 업데이트를 대기열에 넣습니다. React는 렌더링을 더 효율적으로 만들기 위해 여러 업데이트 요청을 함께 일괄 처리 할 수 ​​있습니다. 이로 인해 구성 요소의 이전 상태를 기반으로 상태를 업데이트하려고 할 때 특별한 예방 조치를 취해야합니다.

예를 들어, 다음 코드는 4 번 호출 되었음에도 불구하고 상태 값 속성을 1 씩 증가시킵니다.

 class Counter extends React.Component{
   constructor(props){
     super(props)
    //initial state set up
     this.state = {value:0}
   }
   componentDidMount(){
    //updating state
    this.setState({value:this.state.value+1})
    this.setState({value:this.state.value+1})
    this.setState({value:this.state.value+1})
    this.setState({value:this.state.value+1})
   }
   render(){
    return <div>Message:{this.state.value}</div>
   }
}

상태가 업데이트 된 후 사용하려면 콜백 인수에서 모든 로직을 수행하십시오.

//this.state.count is originally 0
this.setState({count:42}, () => {
  console.log(this.state.count)
//outputs 42
})

setState (updater, [callback]) 메서드는 업데이트 프로그램 함수를 첫 번째 인수로 사용하여 이전 상태 및 속성을 기반으로 상태를 업데이트 할 수 있습니다. 업데이트 프로그램 함수의 반환 값은 이전 구성 요소 상태와 얕게 병합됩니다. 이 메서드는 상태를 비동기 적으로 업데이트하므로 상태가 완전히 업데이트되면 호출되는 옵션 콜백이 있습니다.

예:

this.setState((prevState, props) => { 
return {attribute:"value"}
})

다음은 이전 상태를 기반으로 상태를 업데이트하는 방법의 예입니다.

    class Counter extends React.Component{
      constructor(props) {
        super(props)
    //initial state set up
        this.state = {message:"initial message"}
    }
      componentDidMount() {
    //updating state
        this.setState((prevState, props) => {
          return {message: prevState.message + '!'}
        })
     }
     render(){
       return <div>Message:{this.state.message}</div>
     }
  }

아,에 대해 몰랐습니다. 그것에 대해 setState(updater,[callback])덜 장황한 Object.assign감사입니다!
AJ Venturella

1
@Biboswan, 안녕하세요, 저는 React를 처음 사용하며 CompountDidMount 메서드 내의 4 개의 setState가 모두 병합되고 마지막 setState 만 실행되지만 나머지 3 개는 무시된다는 것이 사실인지 묻고 싶습니다.
Dickens
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.