1

と の 2 台のマシンがAuthenticationMachineありAddressMachineます。AuthenticationMachine は によって使用されLogin component、AddressMachine は によって使用されAddress componentます。しかしtoken、AddressMachine で使用するには、Address コンポーネントの AuthenticationMachine が必要です。ActorAuthenticationMachine で生成しようとしましたが、うまくいきませんでした。

認証機

const createService = (context: {token: string}) => {
  return Machine({
    id: 'service',
    initial: 'logged_in',
    states: {
      logged_in: {},
      logged_out: {},
    },
  }).withContext(context);
};

const authenticationMachine = Machine(
  {
    id: 'authenticationMachine',
    initial: 'unauthenticated',
    context: {
      token: undefined,
      error: undefined,
      service: undefined,
    },
    states: {
      unauthenticated: {
        on: {
          LOGIN: 'authenticating',
        },
      },
      authenticating: {
        invoke: {
          src: 'login',
          onDone: {
            target: 'loggedIn',
            actions: assign({
              token: (ctx, event: any) => event.data.access_token,
              service: (ctx, event) => {
                return spawn(createService({token: event.data.access_token}));
              },
            }),
          },
          onError: {
            target: 'unauthenticated',
            actions: assign({
              error: (ctx, event: any) => event.data,
            }),
          },
        },
      },
      loggedIn: {
        on: {
          LOGOUT: 'unauthenticated'
        },
      },
    },
  },
);
4

1 に答える 1

1

assign の使用、またはコンポーネントの実装方法が問題である可能性があると思います。

これは、コードサンドボックスのコンポーネント内のマシンの動作例です

また、コンポーネントでマシンを使用する方法の簡単な例:

住所コンポーネント:

function Address(props) {
  const [current] = useService(props.service);
  return <>Address Component token: {current.context.token}</>;
}

ログイン コンポーネント:

export default function Login() {
  const [current, send] = useMachine(authenticationMachine);
  const isUnauthenticated = current.matches("unauthenticated");
  const isAuthenticating = current.matches("authenticating");
  const isLoggedIn = current.matches("loggedIn");

  if (isUnauthenticated) {
    return (
      <>
        token: {current.context.token}
        <br />
        <button onClick={() => send("LOGIN")}>Login</button>
      </>
    );
  }
  if (isAuthenticating) {
    return <>...hold on, authenticating</>;
  }
  if (isLoggedIn) {
    return (
      <>
        token: {current.context.token}
        <br />
        <button onClick={() => send("LOGOUT")}>Logout</button>
        <br />
        <Address service={current.context.service} />
      </>
    );
  }
}

マシンの例が拡張されました:

import { assign, Machine, spawn } from "xstate";

const createService = (context: { token: string }) => {
    return Machine({
        id: 'service',
        initial: 'logged_in',
        states: {
            logged_in: {},
            logged_out: {},
        },
    }).withContext(context);
};

const login = (ctx) => {
    const { email, pw } = ctx;
    return new Promise((resolve, reject) => {
        if(email === 'a@b.c' && pw === 'abc') {
            return resolve({ token: 'jahsfjkhakjsnfj'});
        } else {
            return reject({ token: undefined });
        }
    });
};

const authenticationMachine = Machine(
    {
        id: 'authenticationMachine',
        initial: 'unauthenticated',
        context: {
            token: undefined,
            error: undefined,
            service: undefined,
            email: 'a@b.c',
            pw: 'abc'
        },
        states: {
            unauthenticated: {
                on: {
                    LOGIN: 'authenticating',
                },
            },
            authenticating: {
                invoke: {
                    id: 'login',
                    src: context => login(context),
                    onDone: {
                        target: 'loggedIn',
                        actions: [
                            assign({ token: (_, event) => event.data.token }),
                            assign({ service: (_, event) => {
                                return spawn(createService({token: event.data.token}));
                            }})
                        ]
                    },
                    onError: { target: 'unauthenticated' },
                },
            },
            loggedIn: {
                on: {
                    LOGOUT: 'unauthenticated'
                },
            },
        },
    }
);

export { authenticationMachine };
于 2019-12-04T10:12:12.213 に答える