developer tip

setState는 상태를 즉시 업데이트하지 않습니다.

optionbox 2020. 11. 10. 08:02
반응형

setState는 상태를 즉시 업데이트하지 않습니다.


onclick 이벤트를 수행 할 때 내 상태가 변경되지 않는 이유를 묻고 싶습니다. 얼마 전에 생성자에서 onclick 함수를 바인딩해야한다고 검색했지만 여전히 상태가 업데이트되지 않습니다. 내 코드는 다음과 같습니다.

import React from 'react';

import Grid from 'react-bootstrap/lib/Grid';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';

import BoardAddModal from 'components/board/BoardAddModal.jsx';

import style from 'styles/boarditem.css';

class BoardAdd extends React.Component {

    constructor(props){
        super(props);

        this.state = {
            boardAddModalShow: false
        }

        this.openAddBoardModal = this.openAddBoardModal.bind(this);
    }
    openAddBoardModal(){
        this.setState({ boardAddModalShow: true });
// After setting a new state it still return a false value
        console.log(this.state.boardAddModalShow);

    }

    render() {

        return (
            <Col lg={3}>
                <a href="javascript:;" className={style.boardItemAdd} onClick={this.openAddBoardModal}>
                    <div className={[style.boardItemContainer,style.boardItemGray].join(' ')}>
                        Create New Board
                    </div>
                </a>



            </Col>
        )
    }
}

export default BoardAdd

이 콜백은 정말 지저분합니다. 대신 async await를 사용하십시오.

async openAddBoardModal(){
    await this.setState({ boardAddModalShow: true });
    console.log(this.state.boardAddModalShow);
}

상태를 변경하는 데 약간의 시간이 필요 console.log(this.state.boardAddModalShow)하며 상태가 변경되기 전에 실행되므로 이전 값을 출력으로 가져옵니다. 따라서 setState 함수에 대한 콜백에 콘솔을 작성해야합니다.

openAddBoardModal(){
        this.setState({ boardAddModalShow: true }, function () {
             console.log(this.state.boardAddModalShow);
        });

}

setState비동기입니다. 이는 한 줄에서 setState를 호출 할 수없고 다음 줄에서 상태가 변경되었다고 가정 할 수 없음을 의미합니다.

React 문서 에 따르면

setState()즉시 변경되지는 않지만 this.state보류 상태 전환을 만듭니다. this.state이 메서드를 호출 한 후 액세스 하면 잠재적으로 기존 값을 반환 할 수 있습니다. setState에 대한 호출의 동기 작업이 보장되지 않으며 성능 향상을 위해 호출이 일괄 처리 될 수 있습니다.

왜 setState를 비동기로 만들까요?

이는 setState가 상태를 변경하고 다시 렌더링하기 때문입니다. 이는 비용이 많이 드는 작업 일 수 있으며 동기식으로 만들면 브라우저가 응답하지 않을 수 있습니다.

따라서 setState 호출은 더 나은 UI 경험과 성능을 위해 비동기식이며 일괄 처리됩니다.


다행히 setState는 콜백을받습니다. 그리고 이것은 우리가 업데이트 된 상태를 얻는 곳입니다. 이 예를 고려하십시오.

this.setState(
    { name: "Mustkeom" },
      () => {                        //callback
        console.log(this.state.name) // Mustkeom
      }
);

따라서 콜백이 발생하면 this.state가 업데이트 된 상태입니다. 콜백에서 변경 / 업데이트 된 데이터를 얻을 수 있습니다.


setSatate는 비동기 함수이므로 이와 같은 콜백으로 상태를 콘솔 화해야합니다.

openAddBoardModal(){
    this.setState({ boardAddModalShow: true }, () => {
        console.log(this.state.boardAddModalShow)
    });
}

setState()항상 구성 요소를 즉시 업데이트하지는 않습니다. 나중에 업데이트를 일괄 처리하거나 연기 할 수 있습니다. 이것은 setState()잠재적 인 함정 을 호출 직후 this.state를 읽도록 합니다. 대신 componentDidUpdate또는 setState콜백 ( setState(updater, callback))을 사용 하세요 .이 중 하나는 업데이트가 적용된 후에 실행됩니다. 이전 상태를 기반으로 상태를 설정해야하는 경우 아래 업데이트 프로그램 인수에 대해 읽어보세요.

setState()shouldComponentUpdate()false를 반환 하지 않는 한 항상 다시 렌더링 합니다. 변경 가능한 객체를 사용하고에서 조건부 렌더링 논리를 구현할 수없는 경우 새 상태가 이전 상태와 다를 때만 shouldComponentUpdate()호출 setState()하면 불필요한 다시 렌더링을 방지 할 수 있습니다.

The first argument is an updater function with the signature:

(state, props) => stateChange

state is a reference to the component state at the time the change is being applied. It should not be directly mutated. Instead, changes should be represented by building a new object based on the input from state and props. For instance, suppose we wanted to increment a value in state by props.step:

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

If you want to track the state is updating or not then the another way of doing the same thing is

_stateUpdated(){
  console.log(this.state. boardAddModalShow);
}

openAddBoardModal(){
  this.setState(
    {boardAddModalShow: true}, 
    this._stateUpdated.bind(this)
  );
}

This way you can call the method "_stateUpdated" every time you try to update the state for debugging.


Yes because setState is an asynchronous function. The best way to set state right after you write set state is by using Object.assign like this: For eg you want to set a property isValid to true, do it like this


Object.assign(this.state, { isValid: true })


You can access updated state just after writing this line.


setState() is asynchronous. The best way to verify if the state is updating would be in the componentDidUpdate() and not to put a console.log(this.state.boardAddModalShow) after this.setState({ boardAddModalShow: true }) .

according to React Docs

Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately


 this.setState({
    isMonthFee: !this.state.isMonthFee,
  }, () => {
    console.log(this.state.isMonthFee);
  })

According to React Docs

React does not guarantee that the state changes are applied immediately. This makes reading this.state right after calling setState() a potential pitfall and can potentially return the existing value due to async nature . Instead, use componentDidUpdate or a setState callback that is executed right after setState operation is successful.Generally we recommend using componentDidUpdate() for such logic instead.

Example:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      counter: 1
    };
  }
  componentDidUpdate() {
    console.log("componentDidUpdate fired");
    console.log("STATE", this.state);
  }

  updateState = () => {
    this.setState(
      (state, props) => {
        return { counter: state.counter + 1 };
      });
  };
  render() {
    return (
      <div className="App">
        <h1>Hello CodeSandbox</h1>
        <h2>Start editing to see some magic happen!</h2>
        <button onClick={this.updateState}>Update State</button>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);


setState is an asynchronous function so you might need to use it as,

this.setState({key:value},()=>{ callYourFunction(this.state.key) });

참고URL : https://stackoverflow.com/questions/41278385/setstate-doesnt-update-the-state-immediately

반응형