일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- JavaScript
- 리액트 네이티브
- 타입스크립트
- TypeScript
- 사용하는 이유
- React Native
- 참조자료형
- 코딩공부
- 비동기
- scss
- git
- react
- 리덕스
- 자바스크립트
- react-router
- Vue3
- useEffect
- http
- html기초
- CSS
- SasS
- 프론트엔드
- 코딩초보
- 코딩독학
- 코린이
- 코딩기초
- 리액트
- redux
- 깃
- async
Archives
- Today
- Total
맨 땅에 프론트엔드 개발자 되기
React state 변경 비동기 처리에 관하여 / 여러 개 state 변경 에러 해결하기 본문
728x90
React의 state 변경 비동기 처리
React 에서 상태 변경을 할 때 setState 혹은 useState Hook을 써서 변경하면 상태 변경 동작은 비동기로 처리된다. (동기/비동기의 차이점을 알아야 밑에 내용이 이해가 가능하다.) React가 상태 변경을 비동기로 처리하는 이유는 효율성 때문이다. 리액트는 상태가 변경될 때마다 재렌더링을 일으키도록 설계되었는데, 만약 한꺼번에 너무 많은 state가 변경될 경우 일일이 재렌더링을 일으킨다면 너무 비효율적이기 때문에 state 값이 변경될 때 React 내부 로직 기준에 따라 한번에 state 변경을 취합해서 재렌더링을 일으킨다. 그리고 그 취합은 16ms 단위로 이루어진다고 한다.
여러 개 State 변경 에러 해결하기
아래 예제는 input 선택 여부에 따라 재고 개수를 하나씩 빼는 임의로 만든 예제다. 만약 과일의 개수가 너무 많아서 한꺼번에 많은 상태 변경이 일어난다면 취합이 여러 번 일어나면서 state는 객체이기 때문에 모든 상태 변경이 적용되지 않고 마지막 실행값만 덮어씌워지는 에러가 발생할 수 있다.
import { useState } from "react"
export default function Sample() {
const [fruits, setFruits] = useState({
apple: {selected: false, stock: 5},
strawberry: {selected: false, stock: 2},
banana: {selected: false, stock: 4},
kiwi: {selected: false, stock: 6}
});
const handleClick = () => {
fruits.apple.selected && setFruits({...fruits, apple: {...fruits.apple, stock: fruits.apple.stock - 1}});
fruits.strawberry.selected && setFruits({...fruits, strawberry: {...fruits.strawberry, stock: fruits.strawberry.stock - 1}});
fruits.banana.selected && setFruits({...fruits, banana: {...fruits.banana, stock: fruits.banana.stock - 1}});
fruits.kiwi.selected && setFruits({...fruits, kiwi: {...fruits.kiwi, stock: fruits.kiwi.stock - 1}});
};
return (
<section className="sample">
<ul className="display-list">
<li className="display-item">
<input type="checkbox" name="apple" onChange={() => setFruits({...fruits, apple: {...fruits.apple, selected: !fruits.apple.selected}})} />
🍎 : {fruits.apple.stock}
</li>
<li className="display-item">
<input type="checkbox" name="strawberry" onChange={() => setFruits({...fruits, strawberry: {...fruits.strawberry, selected: !fruits.strawberry.selected}})} />
🍓 : {fruits.strawberry.stock}
</li>
<li className="display-item">
<input type="checkbox" name="banana" onChange={() => setFruits({...fruits, banana: {...fruits.banana, selected: !fruits.banana.selected}})} />
🍌 : {fruits.banana.stock}
</li>
<li className="display-item">
<input type="checkbox" name="kiwi" onChange={() => setFruits({...fruits, kiwi: {...fruits.kiwi, selected: !fruits.kiwi.selected}})} />
🥝 : {fruits.kiwi.stock}
</li>
</ul>
<div className="btn-wrap">
<button onClick={handleClick}>Checkout</button>
</div>
</section>
)
}
모든 상태 변경을 확실하게 적용시키기 위해서 아래와 같은 코드로 변경할 수 있다.
import { useState } from "react"
export default function Sample() {
const [fruits, setFruits] = useState({
apple: {selected: false, stock: 5},
strawberry: {selected: false, stock: 2},
banana: {selected: false, stock: 4},
kiwi: {selected: false, stock: 6}
});
// setState() 의 매개변수로 이전 상태값을 받아 업데이트 한다.
const handleClick = () => {
fruits.apple.selected && setFruits(prevState => ({...prevState, apple: {...prevState.apple, stock: prevState.apple.stock - 1}}));
fruits.strawberry.selected && setFruits(prevState => ({...prevState, strawberry: {...prevState.strawberry, stock: prevState.strawberry.stock - 1}}));
fruits.banana.selected && setFruits(prevState => ({...prevState, banana: {...prevState.banana, stock: prevState.banana.stock - 1}}));
fruits.kiwi.selected && setFruits(prevState => ({...prevState, kiwi: {...prevState.kiwi, stock: prevState.kiwi.stock - 1}}));
};
return (
<section className="sample">
<ul className="display-list">
<li className="display-item">
<input type="checkbox" name="apple" onChange={() => setFruits({...fruits, apple: {...fruits.apple, selected: !fruits.apple.selected}})} />
🍎 : {fruits.apple.stock}
</li>
<li className="display-item">
<input type="checkbox" name="strawberry" onChange={() => setFruits({...fruits, strawberry: {...fruits.strawberry, selected: !fruits.strawberry.selected}})} />
🍓 : {fruits.strawberry.stock}
</li>
<li className="display-item">
<input type="checkbox" name="banana" onChange={() => setFruits({...fruits, banana: {...fruits.banana, selected: !fruits.banana.selected}})} />
🍌 : {fruits.banana.stock}
</li>
<li className="display-item">
<input type="checkbox" name="kiwi" onChange={() => setFruits({...fruits, kiwi: {...fruits.kiwi, selected: !fruits.kiwi.selected}})} />
🥝 : {fruits.kiwi.stock}
</li>
</ul>
<div className="btn-wrap">
<button onClick={handleClick}>Checkout</button>
</div>
</section>
)
}
setState 함수는 매개변수로 이전 상태값을 받기 때문에 이전 상태값을 받아 로직을 작성해주면 연속 상태 변경을 적용할 수 있다.
리액트는 공부하면 할 수록 너무 재미남😆
728x90
'코딩 공부 일지 > React JS' 카테고리의 다른 글
React 체크박스 전체 선택/해제 기능 구현하기 (15) | 2022.07.06 |
---|---|
Redux 미들웨어란? (0) | 2022.06.19 |
React 부모 컴포넌트에서 자식 컴포넌트 함수 호출하기 - useImperativeHandle (4) | 2022.06.11 |
react-paginate 로 페이지네이션 구현하기 (0) | 2022.06.07 |
리액트에서 useRef를 이용해서 현명하게 setInterval 사용하기 (0) | 2022.05.25 |