[React] 비동기로 이루어지는 setState

정세은·2022년 11월 25일
0

react

목록 보기
2/8
import React, { useState } from "react";

export default function App() {
    const [number, setNumber] = useState(1);

    const add = () => setNumber(number + 1);
    const subtract = () => setNumber(number - 1);
    const multiplyBy2 = () => setNumber( number * 2);
    
    const multiplyBy2AndAddBy1 = () => {
        multiplyBy2();
        add();
    };

    return (
        <div>
            <h1>Number : {number}</h1>
            <div>
                <button onClick={add}>+ 1</button>
                <button onClick={subtract}>- 1</button>
                <button onClick={multiplyBy2}>*2</button>
                <button onClick={multiplyBy2AndAddBy1}>*2 + 1</button>
            </div>
        </div>
    );
}

위의 코드는 현재 버튼의 값을 보여주는 Number와 4개의 버튼으로 이루어져 있다.
기본 값은 1이고, 버튼을 누르면 버튼의 숫자만큼 커지거나 작아지는 방식이다.

multipleBy2AndAddBy1 함수를 보자.

const multiplyBy2AndAddBy1 = () => {
	multiplyBy2(); // number에 x2를 해주고
	add(); // 곱한 값에 +1을 해준다.
};

그리고 결과 화면을 보자.


기본 값은 1, 차례로 [+1], [*2], [*2 + 1] 버튼을 눌러주었다.

나머지는 정상적으로 작동을 하지만 [*2 + 1] 버튼은 값이 +1만 되는 것을 볼 수 있다.

만약, setState가 동기적으로 실행이 됐다면 multiplyBy2()함수가 실행되고 난 후, add()함수가 실행이 됐을 것이다.
하지만 multiplyBy2()는 적용되지 않고 add()함수만 적용된 결과가 보여지고 있다.

이유는 setState가 비동기로 이루어지기 때문이다.

state 업데이트는 병합된다.
setState를 호출할 때 react는 제공한 객체를 현재 state로 병합한다.

const add = () => setNumber(number + 1);
    const subtract = () => setNumber(number - 1);
    const multiplyBy2 = () => setNumber( number * 2);
    
    const multiplyBy2AndAddBy1 = () => {
        multiplyBy2();
        add();
    };
    
Object.assign({ number, number: number * 2, number : number + 1 });

위의 코드 마지막 number는 두번째(number : number * 2)가 계산된 number가 아닌 그냥 가지고 있던 number이다.

이러한 문제를 해결하기 위해서는 숫자를 바로 넘기지 않고 setState에게 함수를 넘겨줘야 한다.
현재의 state(코드 상에서는 number)를 인자로 넘겨주면 된다.

import React, { useState } from "react";

export default function App() {
    const [number, setNumber] = useState(1);

    const add = () => setNumber((number) => number + 1);
    const subtract = () => setNumber((number) => number - 1);
    const multiplyBy2 = () => setNumber((number) => number * 2);
    const multiplyBy2AndAddBy1 = () => {
        multiplyBy2();
        add();
    };

    return (
        <div>
            <h1>Number : {number}</h1>
            <div>
                <button onClick={add}>+ 1</button>
                <button onClick={subtract}>- 1</button>
                <button onClick={multiplyBy2}>*2</button>
                <button onClick={multiplyBy2AndAddBy1}>*2 + 1</button>
            </div>
        </div>
    );
}

이렇게 작성하면 정상적으로 multiplyBy2()함수가 정상적으로 적용되는 것을 볼 수 있다.

위처럼 변경한다고 해서 setState가 동기적으로 실행되는 것은 아니다.
하지만, 함수를 인자로 넘겨주면 다음 병합시에 업데이트 된 number가 인자로 들어가도록 동작하게 되므로 위와 같은 문제를 해결할 수 있다.

0개의 댓글

관련 채용 정보