React setState 콜백을 사용하는 경우


191

반응 구성 요소 상태가 변경되면 render 메소드가 호출됩니다. 따라서 상태가 변경되면 렌더링 메소드 본문에서 작업을 수행 할 수 있습니다. 그러면 setState 콜백에 대한 특별한 사용 사례가 있습니까?


4
현재 무엇을 요구하고 있는지는 확실하지 않습니다. 코드를 포함시킬 수 있습니까?
Davin Tryon

2
setState 콜백은 상태가 DEFINITELY가 변경된 후 수행하려는 작업에 대한 것입니다. setState가 비동기이기 때문에 fx를 호출하고 새로운 상태가로드되는지 확인하려면 콜백이 그 이유입니다.
Jayce444

3
setState 콜백의 사용 사례는 매우 분명합니다. SPECIFIC 상태가 업데이트 된 후 함수를 실행하려고 할 때 사용합니다. 이 함수를 render()대신 사용하면 모든 상태가 업데이트 될 때마다 실행됩니다. 아마도 원하는 것이 아닙니다. 또한 코드를 읽기 어렵고 논리적으로 만들 수 없습니다.
M3RS

답변:


224

예부터이 setState의 작동 asynchronous방법. 즉 setState, this.state변수 호출 후 즉시 변경되지 않습니다. 따라서 상태 변수에 상태를 설정 한 직후 작업을 수행하고 결과를 반환하려면 콜백이 유용합니다.

아래 예를 고려하십시오

....
changeTitle: function changeTitle (event) {
  this.setState({ title: event.target.value });
  this.validateTitle();
},
validateTitle: function validateTitle () {
  if (this.state.title.length === 0) {
    this.setState({ titleError: "Title can't be blank" });
  }
},
....

title유효성 검사가 수행되기 전에 변수가 변경되지 않았으므로 위의 코드가 예상대로 작동하지 않을 수 있습니다. 이제 우리는 render()함수 자체 에서 유효성 검사를 수행 할 수 있다고 생각할 수 있지만 changeTitle 함수 자체에서 코드를보다 체계적이고 이해하기 쉽게 처리 할 수 ​​있다면 더 좋고 깔끔한 방법입니다.

이 경우 콜백이 유용합니다

....
changeTitle: function changeTitle (event) {
  this.setState({ title: event.target.value }, function() {
    this.validateTitle();
  });

},
validateTitle: function validateTitle () {
  if (this.state.title.length === 0) {
    this.setState({ titleError: "Title can't be blank" });
  }
},
....

또 다른 예로는 dispatch상태가 변경되었을 때 원하는 조치와 조치가 있습니다. 다시 render()렌더링 할 때마다 호출되므로 콜백이 아니라 콜백이 필요하므로 콜백이 필요한 많은 시나리오가 가능합니다.

다른 경우는 API Call

특정 상태 변경을 기반으로 API 호출을 수행해야 할 경우가 발생할 수 있습니다. 렌더 메소드에서 수행하는 경우 렌더링이 onState변경 될 때마다 또는 일부 Prop이 Child Component변경으로 전달되어 호출됩니다 .

이 경우 a setState callback를 사용 하여 업데이트 된 상태 값을 API 호출에 전달 하려고합니다.

....
changeTitle: function (event) {
  this.setState({ title: event.target.value }, () => this.APICallFunction());
},
APICallFunction: function () {
  // Call API with the updated value
}
....

3
나는 그것이 비동기 적이라는 것을 이해합니다. 내 질문 만 setState를 콜백 아마도 지원하지 않을 수 있습니다 방법 몸을 렌더링이 사용될 수 있음이 뭔가 특정되어 있었다 (하자 년대에서 떨어져 뭔가 말을 더 나은 코드의 가독성을.)
사힐 자이나교

@SahilJain Validation은 올바른 예입니다. render () 함수에서 처리하지 않으려면 render ()를 변경할 때마다 호출되므로 입력이 변경 될 때만 호출 할 수 있기 때문에 호출됩니다. 함수 자체에서
하기 Shubham 카트리

리 액트는 렌더링하는 동안 상태를 변경하는 것을 금지합니다. 따라서 유효성 검사를 콜백에 넣을 권리.
webdeb

if (this.title.length === 0) {이어야 this.state.title.length합니까?
Dmitry Minkovsky

4
첫 번째 사용 사례는 아마도 좋은 생각이 아닙니다. 다시 렌더링 한 후 setState 콜백이 트리거되므로 아무런 이유없이 이중 렌더링이 발생합니다. 이것이 바로 함수 인수 (업데이트)의 목적입니다. 당신은 그냥 실행할 수 있으며 setState(state => state.title.length ? { titleError: "Title can't be blank" } : null)변경 사항이 쌓입니다. 이중 렌더링이 필요하지 않습니다.
R Esmond

47
this.setState({
    name:'value' 
},() => {
    console.log(this.state.name);
});

14
이 코드 스 니펫은 제한적이고 즉각적인 도움이 될 수 있습니다. 적절한 설명은 크게 장기 가치를 향상 할 보여줌으로써 이 문제에 대한 좋은 해결책이고, 다른 유사한 질문을 미래의 독자들에게 더 유용 할 것입니다. 제발 편집 당신이 만든 가정 등 일부 설명을 추가 할 답변을.
Machavity

1
상태가 변경된 후 함수를 호출하려면 메소드를 사용할 수 있습니다.
Araz Babayev

이름, 이름 등과 같은 여러 상태를 설정하려면 어떻게해야합니까?
Sumanth Varada

44

내 마음에 오는 유스 케이스는 api호출이며 each상태 변경을 위해 실행되므로 렌더링에 들어가면 안됩니다 . 그리고 API 호출은 모든 렌더링이 아닌 특수 상태 변경에서만 수행되어야합니다 .

changeSearchParams = (params) => {
  this.setState({ params }, this.performSearch)
} 

performSearch = () => {
  API.search(this.state.params, (result) => {
    this.setState({ result })
  });
}

따라서 상태가 변경되면 렌더링 메소드 본문에서 작업을 수행 할 수 있습니다.

-render 나의 방법이 순수해야 하기 때문에 아주 나쁜 방법입니다 . 즉, 조치, 상태 변경, API 호출을 수행하지 말고 뷰를 합성하여 반환해야합니다. 일부 이벤트에서만 작업을 수행해야합니다. 렌더링은 이벤트가 아니라 componentDidMount예를 들어.


25

setState 호출을 고려하십시오

this.setState({ counter: this.state.counter + 1 })

생각

비동기 함수에서 setState를 호출 할 수 있음

따라서 당신은 의지 할 수 없습니다 this. 위의 호출이 비동기 함수 내에서 이루어진 경우 this해당 시점의 구성 요소 상태를 참조하지만 setState 호출 또는 비동기 작업 시작시의 상태 내부 특성을 참조 할 것으로 예상됩니다. 그리고 작업이 비동기 호출이므로 속성이 시간이 지남에 따라 변경되었을 수 있습니다. 따라서 this키워드를 사용하여 상태의 일부 속성을 참조 하는 것은 신뢰할 수 없으므로 인수가 previousState 및 props 인 콜백 함수를 사용합니다. 이는 비동기 작업이 완료되고 setState를 사용하여 상태를 업데이트하는 시간을 의미합니다. prevState는 setState 일 때 현재 상태를 참조합니다 아직 시작하지 않았습니다. nextState가 손상되지 않도록 신뢰성을 보장하십시오.

잘못된 코드 : 데이터가 손상 될 수 있습니다

this.setState(
   {counter:this.state.counter+1}
 );

콜백 함수가있는 setState를 가진 올바른 코드 :

 this.setState(
       (prevState,props)=>{
           return {counter:prevState.counter+1};
        }
    );

따라서 속성에 의해 부여 된 값을 기반으로 현재 상태를 다음 상태로 업데이트해야 할 때마다 비동기 방식으로 setState를 사용하는 것이 좋습니다.

코드 펜으로 여기에 설명하려고했습니다. 코드 펜

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.