상태 관리: 좋은 부울에서 나쁜 부울을 구별하는 방법

9466 단어 webdevtutorial
요약: 잘못된 부울은 상태를 나타냅니다. 좋은 부울은 상태에서 파생됩니다.

앱에서 상태를 관리할 때 잘못된 부울의 희생양이 되기 쉽습니다. 잘못된 부울은 다음과 같습니다.

let isLoading = true;
let isComplete = false;
let hasErrored = false;


표면적으로는 좋은 코드처럼 보입니다. 적절한 부울 이름으로 세 개의 개별 상태를 표현한 것처럼 보입니다. 당신이 당신의 상태에 대해 그린 '모델'에서 한 번에 이러한 상태 중 하나만 참일 수 있습니다.

가져오기 요청에서 다음과 같은 상태를 모델링할 수 있습니다.

const makeFetch = async () => {
  isLoading = true;
  try {
    await fetch('/users');

    isComplete = true;
  } catch (e) {
    hasErrored = true;
  }
  isLoading = false;
};


이번에도 멋지네요. 비동기 요청을 진행하면서 부울을 조정하고 있습니다.

하지만 여기에 버그가 있습니다. 가져오기를 수행하고 성공하고 가져오기를 다시 수행하면 어떻게 됩니까? 우리는 다음과 같이 끝낼 것입니다.

let isLoading = true;
let isComplete = true;
let hasErrored = false;


암시적 상태



초기 모델을 만들 때 이것을 고려하지 않았을 것입니다. isComplete === true 또는 isLoading === true 를 확인하는 프런트엔드 구성 요소가 있을 수 있습니다. 로딩 스피너와 이전 데이터가 동시에 표시될 수 있습니다.

이것이 어떻게 가능한지? 글쎄, 당신은 몇 가지 암시적 상태를 만들었습니다. 실제로 처리하고 싶은 3가지 상태를 고려했다고 가정해 보겠습니다.
  • loading : 데이터 로드 중
  • complete : 데이터 표시 중
  • errored : 데이터가 표시되지 않는 경우 오류 발생

  • 음, 실제로 8개 상태를 허용했습니다! 첫 번째 부울은 2, 두 번째는 2, 세 번째는 2입니다.

    이것이 부울 폭발로 알려진 것입니다. Kyle Shevlin's egghead course에서 이에 대해 배웠습니다.

    상태를 명시적으로 만들기



    이 문제를 어떻게 해결합니까? 가능한 값이 8개인 시스템 대신 가능한 값이 3개인 시스템이 필요합니다. 열거형을 사용하여 Typescript에서 이 작업을 수행할 수 있습니다.

    type Status = 'loading' | 'complete' | 'errored';
    
    let status: Status = 'loading';
    


    다음과 같이 가져오기에서 이를 구현합니다.

    const makeFetch = async () => {
      status = 'loading';
      try {
        await fetch('/users');
    
        status = 'complete';
      } catch (e) {
        status = 'errored';
      }
    };
    


    이제 한 번에 '로드 중' 및 '완료' 상태에 있는 것이 불가능합니다. 버그가 수정되었습니다. 나쁜 부울을 좋은 열거형으로 바꿨습니다.

    좋은 부울 만들기



    그러나 모든 부울이 나쁜 것은 아닙니다. react-query , apollourql 와 같은 많은 인기 있는 라이브러리는 해당 상태에서 부울을 사용합니다. 구현 예:

    const [result] = useQuery();
    
    if (result.isLoading) {
      return <div>Loading...</div>;
    }
    


    이것이 좋은 부울인 이유는 기본 메커니즘이 열거형을 기반으로 하기 때문입니다. 잘못된 부울은 상태를 나타냅니다. 좋은 부울은 다음 상태에서 파생됩니다.

    let status: Status = 'loading';
    
    // Derived from the status above
    let isLoading = status === 'loading';
    


    이 기능isLoading을 안전하게 사용하여 모든 불가능한 상태를 제거했다는 사실에 만족하면서 로딩 스피너를 표시할 수 있습니다.

    부록: Javascript의 열거형



    댓글에 있는 몇몇 사람들이 Javascript에서 상태 열거형을 어떻게 표현하는지 묻고 있습니다. 위의 코드는 타이핑 없이 작동하지만 enum을 객체 유형으로 나타낼 수도 있습니다.

    const statusEnum = {
      loading: 'loading',
      complete: 'complete',
      errored: 'errored',
    };
    
    let status = statusEnum.loading;
    
    const makeFetch = async () => {
      status = statusEnum.loading;
      try {
        await fetch('/users');
    
        status = statusEnum.complete;
      } catch (e) {
        status = statusEnum.errored;
      }
    };
    

    좋은 웹페이지 즐겨찾기