연속 상태 업데이트에서 복수 선택 유지

이 글의 목차 7개 항목

문제와 원인

복수 선택 함수를 한 이벤트에서 ①·② 순서로 호출하면 두 호출 모두 같은 렌더의 selected=[]를 읽었다. [0]과 [1]이 차례로 상태 큐에 들어가 마지막 [1]만 남았다.

수정 전 코드

toggleAnswer

const next = currentQuestion.kind === "single"
  ? [index]
  : selected.includes(index)
    ? selected.filter(item => item !== index)
    : [...selected, index];

setSelected(next);
if (bookmarkPractice) {
  setBookmarkAnswers((previous) => ({ ...previous, [String(currentQuestion.id)]: next }));
}

수정 후 코드

toggleAnswer

완성 배열 대신 updater 함수를 전달해 앞선 갱신 결과로 다음 선택을 계산한다. selected와 문항별 bookmarkAnswers에 같은 선택·해제 함수를 적용했다.

function toggleAnswer(index: number) {
  if (!currentQuestion || revealed || practiceGradingRef.current) return;

  const toggle = (answers: number[]) =>
    currentQuestion.kind === "single"
      ? [index]
      : answers.includes(index)
        ? answers.filter(item => item !== index)
        : [...answers, index];

  setSelected(toggle);

  if (bookmarkPractice) {
    setBookmarkAnswers(previous => ({
      ...previous,
      [String(currentQuestion.id)]:
        toggle(previous[String(currentQuestion.id)] ?? []),
    }));
  }
}

첫 updater가 []를 [0]으로 바꾸면 다음 updater는 [0]에서 [0,1]을 만든다. 단일 선택은 마지막 답 하나로 교체하고, 복수 선택은 포함 여부에 따라 추가·해제한다.

검증 결과

같은 React 격리 화면에서 수정 전후 구현에 입력 시나리오 5개를 적용했다. 한 이벤트의 ①·② 연속 입력은 최종 반영이 1/2개·50%에서 2/2개·100%로 바뀌었다.

입력 조건기대 결과수정 전수정 후
별개의 클릭 ① → ②①·②①·②①·②
① 더블클릭선택 없음선택 없음선택 없음
별개의 클릭 ① → ② → ③①·②·③①·②·③①·②·③
단일 선택에서 ① → ②②②②
한 이벤트에서 ①·② 연속 호출①·②②①·②

문항 1에서 ①·② 선택 → 문항 2에서 ③ 선택 → 문항 1 복귀 시 두 구현 모두 ①·②를 복원했다. 채점 시작 시 포착한 답안도 [0,1]이었다.

같은 이벤트 안의 추가·해제 연산은 아래 입력으로 계산했다.

초기 선택과 입력수정 전 계산수정 후 계산
[]에서 ① → ①[0], 두 번째 해제 누락[], 추가 후 해제
[0]에서 ① 해제 → ② 선택[0,1], ① 재포함[1], 해제 결과 유지

동일 이벤트의 상태 큐

로컬 Node에서 원본 toggleAnswer의 상태 갱신을 호출 순서대로 적용했다. 초기 선택 배열은 []이며 같은 이벤트 안의 네 입력을 각 1회 실행했다. 인덱스 0·1·2는 보기 ①·②·③에 해당한다. 기대 배열과 같은 결과는 1/4개에서 4/4개로 바뀌었다.

동일 이벤트의 입력수정 전 배열수정 후 배열
복수 선택 ① → ②[1][0,1]
복수 선택 ① → ①[0][]
복수 선택 ① → ② → ③[2][0,1,2]
단일 선택 ① → ②[1][1]
동일 이벤트 큐 4조건의 복수 선택 누락 해소와 단일 선택 유지원본 보기 (새 창)

동일 이벤트 큐 4조건의 복수 선택 누락 해소와 단일 선택 유지

100%원본 보기 (새 창)

확대한 이미지는 상하좌우로 이동할 수 있습니다. 키보드는 이미지 영역에 초점을 두고 방향키를 사용하세요. Esc로 닫습니다.