useState & useEffect 와 함수

hodu·2023년 4월 23일
1

이상형 월드컵을 만들어서 랜덤으로 2명을 뽑아와야한다.
조건이 2가지가 있다.
이미 뽑힌 사람이면 안된다.
2명이 서로 같은 사람이어도 안된다 라는 조건이었다.

이 조건에 맞추어서 작성하였더니 문제가 생겼다.


const [twoPeople, setTwoPeople] = useState<Contestant[]>([]);

  const [previousIndices, setPreviousIndices] = useState<Number[]>([]);

  useEffect(() => {
    let randomIndex1, randomIndex2;
    do {
      randomIndex1 = Math.floor(Math.random() * contestants.length);
      randomIndex2 = Math.floor(Math.random() * contestants.length);
    } while (
      randomIndex1 === randomIndex2 ||
      previousIndices.includes(randomIndex1) ||
      previousIndices.includes(randomIndex2)
    );
    setTwoPeople([contestants[randomIndex1], contestants[randomIndex2]]);
    setPreviousIndices([randomIndex1, randomIndex2]);
  }, [contestants, previousIndices]);
  

해당 코드를 보면 previousIndices와 ,setpreviousIndices가 꼬리 물기하면서 무한루프에 빠지는 것을 볼 수 있다.


처음에는 previousIndices를 2번째 인자에 넣지 않았고, React에서 이러한 방식을 권장하는 것이 납득이 가지 않았다.

조금만 더 생각해보니, 나의 부족함을 느꼈다.
React에서는 완벽한 통제 즉 예상치 못한 버그가 발생하는 것을 사전에 알려주는 친절이었다.
당연하게도 변하는 값이 있다면, 그것을 인지하고 로직을 짜는게 좋은 로직이다.

    const GroupNumber: Number[] = previousIndices;

라는 것을 작성하여서 회피하려고 하였지만 두번째 인자에 넣어줘야해서 검거 당했다.
useState의 인자라는 것이 중요한 것이아니라 변수라면 넣어줘야하는 것인데
잘못된 시도였다.

고민을 더해보니 useEffect로는 불가능하다는 판단이 나왔고,

이를 바로 잡기 위해 함수로 해결하기로 하였다.

함수로 하면 좋은 것이 useEffect는 훅이기때문에 React 조건에 맞추어서 사용하여야하지만,
내가 함수를 디자인한다면 좀 더 컨트롤이 쉬울 것 같다는 생각이 들었다.

그래서 최근 알고리즘을 했던 기억을 착안해서 두가지 함수로 쪼개어
로직을 간단히 하는 방향으로 고민하였다.

1번째, 2명을 저장하고, 기존에 배열에서 삭제할 것(검증을 안해도 된다)
2번째, 2명이 같은 사람인지 검증하는 로직을 작성하기로 하였다.

고민 끝에 아래처럼 작성하였다.

 const randomIndex = (el: number) => {
    let num = Math.floor(Math.random() * contestants.length);
    while (el === num) {
      num = Math.floor(Math.random() * contestants.length);
    }
    return num;
  };
  // 겹치지 않는 2명을 계속해서 뽑는 법
  const randomContestant = () => {
    const randomIndex1 = Math.floor(Math.random() * contestants.length);
    const randomIndex2 = randomIndex(randomIndex1);
    const randomContestant1 = contestants[randomIndex1];
    const randomContestant2 = contestants[randomIndex2];
    setTwoPeople([randomContestant1, randomContestant2]);
    setContestants(
      contestants.filter(
        (el) => el !== randomContestant1 && el !== randomContestant2
      )
    );
  };

위와 같은 로직을 작성하여서 해결하였다.

내가 원하는 상황에 맞추어서 이 함수가 발동되도록 조건을 걸었고,

컨트롤이 더 쉬워졌다.

무한 루프에 걸리지 않고 내가 원하는 랜덤 2명과 12명에서 2명이 삭제된 결과값이 나왔다
성공!



배운점

프리온 보딩에서 useEffect를 가능하면 쓰지말라는 말이 더 와닿기 시작했다.
이론으로 배웠던 것을 실제로 적용하는 사례가 생겨서 좋은 경험이 되었다.

나는 항상 생각할때 상황에 맞추어 useEffect를 사용하는 경우의 수가 먼저 떠오르는데,
이 일을 계기로 함수를 먼저 고려할 것 같다.

강의와 경험이 어우러진 큰 수확이었고, 성장했음이 느껴져 만족스럽다.

profile
잘부탁드립니다.

0개의 댓글