XState: 호출된 콜백을 좋아하는 이유

14895 단어 webdevxstate
XState는 장기 실행 애플리케이션 프로세스를 나타내는 몇 가지 프리미티브를 제공합니다. 이들은 일반적으로 services 으로 표현됩니다. 저는 서비스에 대해 조금 썼습니다. 하지만 오늘은 제가 가장 좋아하는 서비스 표현 방법인 Invoked Callback에 대해 이야기하고 싶었습니다.

Invoked Callback은 우수한 가독성 및 견고한 Typescript 경험과 뛰어난 유연성을 결합합니다. 그들은 다음과 같이 보입니다 :

createMachine({
  invoke: {
    src: (context, event) => (send, onReceive) => {
      // Run any code you like inside here

      return () => {
        // Any code inside here will be called when
        // you leave this state, or the machine is stopped
      };
    },
  },
});


이것을 분해합시다. 약속 기반 서비스와 마찬가지로 contextevent 에 액세스할 수 있습니다. 그러나 send는 일이 정말로 흥미로워지는 곳입니다. 예를 들어 send를 유용하게 만드는 요소를 분석해 보겠습니다.

파일 업로드



파일 업로더를 빌드해야 하고 일부 데이터를 업로드하고 진행률을 업데이트하기 위해 startUpload 매개변수를 노출하는 onProgressUpdate라는 편리한 함수가 있다고 가정해 보십시오.

createMachine({
  context: {
    progress: 0,
  },
  initial: 'idle',
  states: {
    idle: {
      on: {
        START: 'pending',
      },
    },
    pending: {
      on: {
        PROGRESS_UPDATED: {
          assign: assign({
            progress: (context, event) => event.progress,
          }),
        },
        CANCEL: {
          target: 'idle',
        },
      },
      invoke: {
        src: (context) => (send) => {
          const uploader = startUpload({
            onProgressUpdate: (progress) => {
              send({
                type: 'PROGRESS_UPDATED',
                progress,
              });
            },
          });

          return () => {
            uploader.cancel();
          };
        },
      },
    },
  },
});


이 시스템은 idle 상태에서 시작하지만 START 이벤트에서 파일을 업로드하는 호출된 서비스를 시작합니다. 그런 다음 PROGRESS_UPDATED 이벤트를 수신하고 업데이트를 기반으로 컨텍스트를 업데이트합니다.
CANCEL 이벤트는 상태가 떠날 때 호출되는 uploader.cancel() 함수를 트리거합니다. React 사용자는 이 구문을 인식할 수 있습니다. 이는 useEffect hook 의 정리 함수와 동일합니다.

업로더를 취소하는 것이 얼마나 간단하고 관용적인지에 유의하십시오. 상태를 종료하면 서비스가 정리됩니다.

이벤트 리스너



호출된 콜백의 정리 함수는 예를 들어 window.addEventListener() 와 같은 이벤트 리스너에 매우 유용합니다. XState CatalogueTab Focus Machine가 이에 대한 완벽한 예입니다. 쉽게 복사할 수 있습니다.

createMachine(
  {
    initial: 'userIsOnTab',
    states: {
      userIsOnTab: {
        invoke: {
          src: 'checkForDocumentBlur',
        },
        on: {
          REPORT_TAB_BLUR: 'userIsNotOnTab',
        },
      },
      userIsNotOnTab: {
        invoke: {
          src: 'checkForDocumentFocus',
        },
        on: {
          REPORT_TAB_FOCUS: 'userIsOnTab',
        },
      },
    },
  },
  {
    services: {
      checkForDocumentBlur: () => (send) => {
        const listener = () => {
          send('REPORT_TAB_BLUR');
        };

        window.addEventListener('blur', listener);

        return () => {
          window.removeEventListener('blur', listener);
        };
      },
      checkForDocumentFocus: () => (send) => {
        const listener = () => {
          send('REPORT_TAB_FOCUS');
        };

        window.addEventListener('focus', listener);

        return () => {
          window.removeEventListener('focus', listener);
        };
      },
    },
  },
);

userIsOnTab 상태에 있을 때 창의 blur 이벤트를 수신합니다. 그런 일이 발생하고 REPORT_TAB_BLUR가 실행되면 이벤트 리스너를 정리하고 바로 userIsNotOnTab로 이동하여 다른 서비스를 실행합니다.

웹소켓



호출된 콜백은 onReceive 함수를 통해 이벤트를 수신할 수도 있습니다. 이는 websocket에 이벤트를 보내는 것과 같이 서비스와 통신해야 할 때 완벽합니다.

import { createMachine, forwardTo } from 'xstate';

createMachine({
  on: {
    SEND: {
      actions: forwardTo('websocket'),
    },
  },
  invoke: {
    id: 'websocket',
    src: () => (send, onReceive) => {
      const websocket = connectWebsocket();

      onReceive((event) => {
        if (event.type === 'SEND') {
          websocket.send(event.message);
        }
      });

      return () => {
        websocket.disconnect();
      };
    },
  },
});


이벤트를 수신하려면 서비스에 id 가 필요합니다. 모든 이벤트가 호출된 서비스로 전달되는 것은 아니며 forwardTo 작업을 통해 선택한 이벤트만 전달됩니다.

여기에서 websocket에 연결하고 양방향 통신을 설정하고 몇 줄의 코드로 정리할 수 있습니다.

내 사랑의 편지



호출된 콜백은 XState에서 서비스를 호출하는 간결하고 유연한 방법입니다. 처리할 수 없는 경우가 없으며 XState API에서 제가 가장 좋아하는 부분 중 하나입니다.

좋은 웹페이지 즐겨찾기