Vuex를 XState로 교체

10157 단어 vuexstatevuex
저는 지난 몇 달 동안 XState와 상태 머신을 배웠고 정말 좋아합니다. Vue와 XState를 사용하여 앱을 빌드하기로 결정했습니다. XState를 React와 통합하는 방법에 대한 많은 게시물, 비디오, 자습서 등을 보았기 때문에 이것을 여러분 모두와 공유하고 싶었지만 Vue에서는 많지 않았습니다.

처음에는 XState와 함께 Vuex를 사용했습니다. 나는 Phillip Parker의 이것article과 같은 작가의 이것Github repo에서 많은 영감을 받았습니다. 나는 당신이 기사를 읽고 코드를 아직 확인하지 않았다면 확인하는 것이 좋습니다. 나는 그것에서 많은 것을 배웠습니다.

기본적으로 앱의 모든 기능에 대해 Vuex 모듈과 해당 XState 상태 머신이 있었습니다. 잘 작동하고 있었지만 XState를 최대한 활용하고 있지 않다는 것을 알고 있었습니다.

더 많은 연구 끝에 Vuex를 완전히 제거하고 XState가 제공하는 모든 기능을 사용할 수 있게 하는 견고한 Finite State Machine과 함께 Vue의 기능을 활용하는 전역 반응 상태를 유지하는 방법을 찾았습니다. XState의 문서에 표시된 Vue recipe과 더 유사합니다.

Vuex 대신 이벤트 버스 패턴을 사용하여 전역 상태를 관리합니다. 이것은 새 Vue 인스턴스를 만들고 구성 요소 간에 공유하려는 모든 것을 전달하는 것을 의미합니다. 간단한 앱의 경우 하나의 인스턴스일 수 있지만 대부분의 앱은 Vuex와 같이 여러 모듈로 나누는 것이 좋습니다.

그런 다음 XState 시스템에서 필요한 것을 이 Vue 인스턴스에 간단히 전달할 수 있습니다. 머신의 상태, 컨텍스트 및 send() 메서드를 노출하고 머신의 변경 사항에 반응하는 Vue 인스턴스를 반환하는 함수를 작성했습니다.

import Vue from "vue";
import { interpret } from "xstate";

export const generateVueMachine = machine => {
    return new Vue({
        created() {
            this.service
                .onTransition(state => {
                    this.current = state;
                    this.context = state.context;
                    if (process.env.NODE_ENV === "development") {
                        console.log(`[ ${machine.id.toUpperCase()} STATE ]`, this.current.value);
                    }
                })
                .start();
        },
        data() {
            return {
                current: machine.initialState,
                context: machine.context,
                service: interpret(machine)
            };
        },
        methods: {
            send(event) {
                this.service.send(event);
            }
        }
    });
};

그런 다음 XState 머신을 생성하는 fetchMachine.js와 같은 새 파일을 작성할 수 있습니다. generateVueMachine() 함수를 사용하여 상태 머신을 인수로 전달하면 내보낼 수 있는 Vue 인스턴스가 반환됩니다.

import { Machine, assign } from "xstate";
import { generateVueMachine } from "./generateVueMachine";

const machine = Machine({ /*...machine config */ });

export const fetchMachine = generateVueMachine(machine);

이제 내 앱에서 원하는 곳 어디에서나 이 시스템을 참조하고 Vue의 계산된 속성을 사용하여 변경 사항에 반응할 수 있습니다.

<template>
    <button @click="onFetch" v-if="!fetchState.matches('fetching')">Fetch<button>
    <p>{{ fetchContext.fetchResult }}</p>
</template>

<script>
// fsm
import { fetchMachine } from "./fsm/fetchMachine";

export default {
    computed: {
        fetchState() {
            return fetchMachine.current;
        },
        fetchContext() {
            return fetchMachine.context;
        }
    },
    methods: {
        onFetch() {
            fetchMachine.send({type: 'FETCH'});
        }
    }
};
</script>

그리고 그게 다야.

여기 내 앱의 저장소에 대한 link이 있으므로 실제 컨텍스트에서 이것을 적용한 방법을 볼 수 있습니다(상태 시스템 파일은 client/fsm에 있음).

여기서 더 잘할 수 있는 것에 대한 피드백을 주시면 정말 감사하겠습니다.

편집하다:
이 설정을 용이하게 하기 위해 npm에 Vue 플러그인을 만들었습니다. 보일러 플레이트의 일부를 제거합니다. https://github.com/f-elix/vue-xstate-plugin 에서 찾을 수 있습니다.

좋은 웹페이지 즐겨찾기