728x90
반응형
회고 페이지를 만드는데 답을 배열로 받는 질문만 로컬스토리지 복원이 잘 안되는 문제가 생겼다.
1. console.log를 찍어 보면, 로컬스토리지에서 데이터를 잘 복원하고 setAnswer3로 상태를 업데이트한다. 그런데 그 직후, answer3가 다시 ["", "", ""]로 초기화된다.
2. answer1과 answer2 같은 문자열 상태에서는 이런 일이 없었음. 왜 배열만 이런 일이?
리액트 DOM 렌더링 순서
- useState 초기값 적용
- 컴포넌트가 처음 렌더링될 때, useState로 설정된 초기값이 DOM에 반영된다.
- 이 코드에서 초기값 ["", "", ""]가 DOM에 먼저 반영된다.
-
const [answer3, setAnswer3] = useState(["", "", ""]);
- useEffect 실행
- 첫 번째 렌더링이 완료된 후, useEffect가 실행되면서 로컬스토리지 데이터를 복원한다.
- 복원된 값으로 setAnswer3를 호출하면 상태가 업데이트되고, 컴포넌트가 재렌더링된다.
- 로컬스토리지 값 덮어쓰기
- 복원된 상태 값(answer3)이 변경되면, useEffect에서 이를 로컬스토리지에 저장한다.
- 문제는, 초기값 ["", "", ""]도 로컬스토리지에 저장될 수 있다는 것. answer이 변경되면 로컬스토리지에 저장하는 의존성 배열이 있는 useEffect 가 실행되어 자꾸 "", "", "" 로 저장되는 것이었음..
// 원래 코드
useEffect(() => {
localStorage.setItem("answer1", answer1);
localStorage.setItem("answer2", answer2);
localStorage.setItem("answer3", answer3);
}, [answer1, answer2, answer3]);
(문제가 왜 answer3(배열) 에서만 생기냐고,,, )
- answer1, answer2는 문자열(string)
- 문자열은 값형 데이터(primitive type)라서 상태 변경 시 값 자체가 대체된다.
- 문자열 상태에서는 초기값 덮어쓰기가 상대적으로 간단하다.
- answer3은 배열(array)
- 배열은 참조형 데이터(reference type)라서 상태를 변경할 때 반드시 새로운 참조를 생성해야 한다.
- React는 참조를 기준으로 상태 변경을 감지하므로, 참조가 유지되면 상태 변경을 제대로 인식하지 못하거나, 의도치 않게 초기화 로직이 중복될 수 있다.
(배열은 불변성 - 알맹이 그대로 두고 새 배열을 만들어서 참조를 바꾸는 식으로 사용함)
해결방법
useEffect(() => {
localStorage.setItem("answer1", answer1);
localStorage.setItem("answer2", answer2);
if (answer3 && answer3.some((val) => val.trim() !== "")) {
localStorage.setItem("answer3", JSON.stringify(answer3));
}
}, [answer1, answer2, answer3]);
빈 배열은 저장하지 않기
- 배열 answer3에 값이 하나도 없으면 로컬스토리지에 저장하지 않는다.
- 배열 안에 하나라도 비어 있지 않은 값이 있을 때만 저장하도록 조건을 건다.
이제 "", "", "" 로 초기화된 상태에선
728x90
반응형
'프론트엔드✏️ > 개인공부' 카테고리의 다른 글
[Next.js] [MongoDB] CRUD의 Create, Read 연결하기 (0) | 2024.05.06 |
---|---|
[flutter] 설치부터 난관. (1) | 2024.02.24 |
[firebase] Firebase 이메일 중복확인 (0) | 2023.07.28 |
gyp ERR! (0) | 2023.04.07 |
[git] (0) | 2023.04.06 |