원티드 프리온보딩 2월 인턴쉽 선발과제 하던 중
todo 수정버튼을 누르면 개별적으로 수정 창이 열리도록 구현하던 중이었다.
todos는 axios로 api의 응답을 불러온 배열이고
todo 데이터의 길이만큼 false값이 담긴 배열을 새 배열로 복사하고 싶어 다음과 같이 작성하였다.
//Todos.tsx
const { todos } = useFetch();
const [isEditTodo, setIsEditTodo] = useState(
Array.from({ length: todos?.length }, () => false)
); //todo 데이터의 길이만큼 false가 담긴 배열 생성
여기서 isEditTodo 값을 확인해 보면 빈 배열로 나온다.
하지만 length를 todos?.length가 아닌 임의로 number값을 넣으면 배열이 잘 생성된다..
todos?.length의 type은 number로 정의되어 있다.
만약 TodoList가 2개 있다고 가정하면
처음 랜더링시 todos?.length는 0으로 출력되다가 2로 또 한번 출력이 되는 걸 확인 할 수 있었다.
구글링으로 열심히 찾아본 결과 setState 함수는 비동기로 처리되기 때문이라서 이전의 결과를 출력해주는 것이 원인이었다. 그래서 복사한 배열이 계속 빈 배열로 나온 것이었다.
// Todos.tsx
const { todos } = useFetch();
//수정 전
const [isEditTodo, setIsEditTodo] = useState(
Array.from({ length: todos?.length }, () => false
));
//수정 후
const [isEditTodo, setIsEditTodo] = useState<boolean[]>([]);
/// TodoUtilButton.tsx
//수정 버튼 클릭 함수
const editHandler = (event: MouseEvent<HTMLButtonElement>) => {
//todo의 길이만큼 false값이 담긴 새 배열 복사
const todosEditBooleanArray = Array.from(
{ length: todos.length },
() => false
);
setIsEditTodo(todosEditBooleanArray); //fasle값이 담긴 새 배열을 setState 함수에 넣어준다.
//배열 복사
let newIsEditTodo = [...isEditTodo];
if (isEditTodo[index] === false) {
newIsEditTodo[index] = true;
setIsEditTodo([newIsEditTodo]);
}
};