TIL 116. 2024-06-14

이준구·2024년 8월 14일
0

TIL 순서

목록 보기
118/119
post-thumbnail

CheckModal UI 깜빡이는 현상



const CheckModal = () => {
  const title = useGroupModalElement();
  const voteResults = useVoteResultElement();
  const [isVote, setIsVote] = useState(true);

  const diedPlayerId = useDiedPlayer();
  const { localParticipant } = useLocalParticipant();
  const localPlayerId = localParticipant.identity;

  //NOTE - 가장 많은 투표 수를 받는 player
  const votePlayer = voteResults[0];

  //NOTE - 가장 많은 투표를 받은 player가 자신일 경우
  useEffect(() => {
    if (votePlayer.user_id === localPlayerId) {
      setIsVote(false);
    }
  }, [votePlayer]);

  //NOTE - 죽은 playerId
  const isDiedPlayer = diedPlayerId.find((playerId) => localPlayerId === playerId);

  //NOTE - 최후의 투표 클릭 이벤트
  const chooseVoteHandler = (vote: boolean) => {
    setIsVote(false);
    socket.emit("voteYesOrNo", vote);
  };

  return (
    <>
      <div className={S.modalWrap}>
        <div className={S.modal}>
          <div>
            <h1>{title}</h1>
            {isVote && !isDiedPlayer ? (
              <>
                <div className={S.userCheckNickName}>
                  <p>
                    <strong>{votePlayer.user_nickname}</strong> 님을
                    <br /> 최종적으로 지목하시겠습니까?
                  </p>
                </div>
                <div className={S.checkButton}>
                  <button disabled={!isVote} onClick={() => chooseVoteHandler(true)}>
                    찬성
                  </button>
                  <button disabled={!isVote} onClick={() => chooseVoteHandler(false)}>
                    반대
                  </button>
                </div>
              </>
            ) : (
              <div>투표 중입니다.</div>
            )}
            <ModalProgress />
          </div>
        </div>
      </div>
    </>
  );
};

export default CheckModal;
  • 위의 코드를 해석해보면, 초기 렌더링시 조건부 UI 형태는 두 가지 경우로 나누어진다.

    1) 투표 참여자이면서, 살아있을경우: "찬성/반대" === isVote, !isDiedPlayer,
    2) 투표 참여자이면서, 죽어있을 경우: "투표 중입니다." === isVote, isDiedPlayer,

  • 초기 렌더링 이후 정상적으로 작동되어야 하는 4가지 경우

    • "찬성/반대"
      1) 투표 참여자이면서, 살아있을 경우 === isVote, !isDiedPlayer,

    • "투표 중입니다."
      1) 투표 참여자이지만, 죽어있을 경우 === isVote, isDiedPlayer
      2) 투표 대상자이면서, 살아있을 경우 === !isVote, !isDiedPlayer
      3) 투표 대상자이면서, 죽어있을 경우 === !isVote, isDiedPlayer

문제:

  • 위의 사진을 보면, 초기 렌더링 당시 UI가 깜빡이는 현상을 볼 수 있다.

해결방법:

  • 아래의 로직을 보시다시피, 초기 state값 및 초기 렌더 필터링을 통해 간단히 UI의 깜빡이는 현상을 해결할 수 있다.
  • 이 문제를 별도의 TIL에 작성한 이유는 간단하게 해결할 수 있지만, 생각보다 오래걸리면서 헷갈렸던 부분이기에 작성해놓는다.
const CheckModal = () => {
  const title = useGroupModalElement();
  const voteResults = useVoteResultElement();
  const [isVote, setIsVote] = useState<boolean | null>(null);

  const diedPlayerId = useDiedPlayer();
  const { localParticipant } = useLocalParticipant();
  const localPlayerId = localParticipant.identity;

  // 가장 많은 투표 수를 받는 player
  const votePlayer = voteResults[0];

  //NOTE - 투표 대상자 or 참여자인 지 여부
  useEffect(() => {
    // 가장 많은 투표를 받은 player가 자신일 경우(투표 대상자)
    if (votePlayer.user_id === localPlayerId) {
      setIsVote(false);
      return;
    }
    // 가장 많은 투표를 받은 player가 자신이 아닌 경우(투표 참여자)
    if (votePlayer.user_id !== localPlayerId) {
      setIsVote(true);
    }
  }, [votePlayer]);

  //NOTE - 죽은 playerId
  const isDiedPlayer = diedPlayerId.find((playerId) => localPlayerId === playerId);

  //NOTE - 최후의 투표 클릭 이벤트
  const chooseVoteHandler = (vote: boolean) => {
    setIsVote(false);
    socket.emit("voteYesOrNo", vote);
  };

  //NOTE - 초기 렌더링 필터
  if (isVote === null) {
    return;
  }

  return (
    <>
      <div className={S.modalWrap}>
        <div className={S.modal}>
          <div>
            <h1>{title}</h1>
            {isVote && !isDiedPlayer ? (
              <>
                <div className={S.userCheckNickName}>
                  <p>
                    <strong>{votePlayer.user_nickname}</strong> 님을
                    <br /> 최종적으로 지목하시겠습니까?
                  </p>
                </div>
                <div className={S.checkButton}>
                  <button disabled={isVote} onClick={() => chooseVoteHandler(true)}>
                    찬성
                  </button>
                  <button disabled={isVote} onClick={() => chooseVoteHandler(false)}>
                    반대
                  </button>
                </div>
              </>
            ) : (
              <div>투표 중입니다.</div>
            )}
            <ModalProgress />
          </div>
        </div>
      </div>
    </>
  );
};

export default CheckModal;
profile
개발 중~~~ 내 자신도 발전 중😂🤣

0개의 댓글

관련 채용 정보