안녕하세요. 박기린 입니다.
여러 State 생성하기
const [enteredTitle, setEnteredTitle] = useState("");
const [enteredAmount, setEnteredAmount] = useState("");
const [enteredDate, setEnteredDate] = useState("");
const [counter, setCounter] = useState(1);
한 파일(컴포넌트) 안에 위처럼 여러 개의 state를 설정할 수 있습니다.
const titleChangeHandler = (event) => {
setEnteredTitle(event.target.value);
};
const amountChangeHandler = (event) => {
setEnteredAmount(event.target.value);
};
const dateChangeHandler = (event) => {
setEnteredDate(event.target.value);
};
바뀐 값을 저장하기 위해 setState()를 사용합니다. setState()를 사용해서 state를 저장하면, 컴포넌트 함수의 수명 주기와는 별개로 값을 저장할 수 있습니다. 그래서 컴포넌트 함수가 얼마나 자주 재실행되는 지에 상관없이 state들을 그 값 그대로 잘 저장되어 있습니다.
여러 개의 state를 하나의 state에 몰아넣기
! - 이 위 섹션 내용처럼, 기존의 독립된 state 설정 방식이 보편적으로 쓰이고 있습니다.
이 다음 섹션의 내용이 보편적인 방식은 아닙니다. 하나의 state에 몰아서 사용하는 곳도 있으니, 이에 대해 대응하기 위한 내용을 알려드리고자 합니다. 직접 프로그래밍을 하실 때에는 선호하는 방법을 사용하시길 바랍니다.
// const [enteredTitle, setEnteredTitle] = useState("");
// const [enteredAmount, setEnteredAmount] = useState("");
// const [enteredDate, setEnteredDate] = useState("");
// const [counter, setCounter] = useState(1);
const [userInput, setUserInput] = useState({
enteredTitle: '',
enteredAmount: '',
enteredDate: '',
counter: 1,
});
네 개의 독립적인 state를 갖는 방식이 아니라, 하나의 object state에 모두를 포함시키는 방법이 있습니다.
단, 하나의 state를 업데이트하고 싶더라도 모든 property states를 같이 업데이트 해야만 합니다.
const titleChangeHandler = (event) => {
// setEnteredTitle(event.target.value);
setUserInput({
...userInput,
enteredTitle: event.target.value, // 기존의 enteredTitle을 override.
});
};
const amountChangeHandler = (event) => {
// setEnteredAmount(event.target.value);
setUserInput({
...userInput,
enteredAmount: event.target.value,
});
};
const dateChangeHandler = (event) => {
// setEnteredDate(event.target.value);
setUserInput({
...userInput,
enteredDate: event.target.value,
});
};
setState() 함수는 state 안에 있는 모든 값들을 덮어 씌웁니다. 그래서 인수로 object를 넘길 때, 수정되지 않을 property의 기존 값들도 함께 넘겨줘야 합니다. 이때 JS의 spread 연산자를 사용하면 됩니다.
setState()에 함수를 전달하기
const countChangeHandler = (event) => {
setUserInput({
...userInput,
counter: event.target.value;
});
setUserInput({
...userInput,
counter: counter++;
});
};
이처럼 여러 개의 setState()를 한 핸들러 함수에서 사용해야 되는 경우, 전개 연산자를 활용한 방식은 문제가 생깁니다.
왜나하면, setState()는 비동기로 작동하기 때문입니다.
[ https://arnopark.tistory.com/592 이 글의 '비동기로 작동하는 setState() 섹션 확인' ]
// counter : 1
// 유저가 counter로 10을 입력했다고 가정
const countChangeHandler = (event) => {
setUserInput({
...userInput,
counter: event.target.value; // counter : 1 | 예약 : counter를 10으로 수정하기
});
setUserInput({
...userInput,
counter: counter++; // counter : 1 | 예약 : counter에 1 더하기
});
};
// 결과 - counter : 2
위의 주석에 달린 과정에 따라, counter는 11이 아니라 2가 됩니다.
결국, 이러한 방식의 state update는 문제가 있습니다.
이에 대한 대안으로, 함수를 setState()에 전달하는 방법이 있습니다.
const counterChangeHandler = (event) => {
setUserInput((prevState) => {
return { ...prevState, counter: event.target.value };
})
setUserInput((prevState) => {
return { ...prevState, counter: counter++ };
})
};
setState()의 인수로 함수를 전달할 경우, 그 함수는 prevState라는 인수를 받습니다.
prevState에는 state의 가장 최신 snapshot이 담깁니다. 비동기로 작동하는 setState의 상황까지 모두 고려해줍니다.
prevState를 spread 연산자와 함께 사용해주면, 위에서 발생한 오류가 나타나지 않습니다.
'JS > React 강의' 카테고리의 다른 글
[React] 9. 리스트 데이터 출력하기 (0) | 2023.03.03 |
---|---|
[React] 8. <form /> 태그 다루기 (0) | 2023.02.23 |
[React] 6. useState()를 파헤쳐 보기 (0) | 2023.02.13 |
[React] 5. 이벤트 리스너와 이벤트 핸들러 만들기 (onProps) (1) | 2023.02.07 |
[React] 4. JSX란 무엇일까? (0) | 2023.02.07 |