首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XState反应-调用服务未触发

XState反应-调用服务未触发
EN

Stack Overflow用户
提问于 2022-03-08 04:47:08
回答 1查看 432关注 0票数 0

我使用xstatereact来实现基本的登录功能。代码是这里,我面临的问题是,在事件AUTHENTICATING上,它是为了调用服务authenticateUser,而不是调用服务authenticateUser。控制台中没有可见的错误。组件看起来就像

代码语言:javascript
复制
import { useMachine } from "@xstate/react";
import { createMachine, assign } from "xstate";
import "./App.css";

const authenticateUserNew = async (c, e) => {
  console.log("service invoked");
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() > 0.5) {
        resolve();
      } else {
        reject();
      }
    }, 1000);
  });
};

const loginMachine = createMachine(
  {
    id: "login-machine",
    initial: "unauthenticated",
    context: {
      isAuthenticated: false,
    },
    states: {
      unauthenticated: {
        on: {
          AUTHENTICATING: {
            invoke: {
              id: "authenticateUser",
              src: (c, e) => authenticateUserNew(c, e),
              onDone: {
                target: "authenticated",
                actions: assign({ isAuthenticated: (context, event) => true }),
              },
              onError: {},
            },
          },
        },
      },
      authenticated: {
        on: {
          LOGOUT: {
            target: "unauthenticated",
          },
        },
      },
    },
  },
  {
    services: {
      authenticateUser: () => {
        console.log("service invoked");
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            if (Math.random() > 0.5) {
              resolve();
            } else {
              reject();
            }
          }, 1000);
        });
      },
    },
  }
);

function App() {
  const [current, send] = useMachine(loginMachine);
  return (
    <div className="App">
      <h2>{current.value}</h2>
      <br />
      <h3>
        isAuthenticated: {current.context.isAuthenticated ? "True" : "False"}
      </h3>
      <br />
      <button onClick={() => send("AUTHENTICATING")}>AUTHENTICATE</button>
      <br />
      <button onClick={() => send("LOGOUT")}>LOGOUT</button>
    </div>
  );
}

export default App;

我已经尝试过两种方法,在这两种方法中,我都可以将函数外部化并使用它,或者在状态机的service部分中定义它,在这两种情况下都没有调用它。

第一种方法

代码语言:javascript
复制
invoke: {
  id: "authenticateUser",
  src: (c, e) => authenticateUserNew(c, e),
  onDone: {
    target: "authenticated",
    actions: assign({ isAuthenticated: (context, event) => true }),
  },
  onError: {},
}

第二种方法

代码语言:javascript
复制
invoke: {
  id: "authenticateUser",
  src: "authenticateUser",
  onDone: {
    target: "authenticated",
    actions: assign({ isAuthenticated: (context, event) => true }),
  },
  onError: {},
}

React version: ^17.0.2 xstate: ^4.3.5 @xstate/react: 2.0.1

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-08 14:23:05

来自文档

调用是在具有invoke属性的状态节点配置中定义的。

相反,您尝试在事件节点中调用,而不是状态节点。

例如,您可以:

代码语言:javascript
复制
...
    states: {
      unauthenticated: {
        on: {
          AUTHENTICATE: {
            target: 'authenticating'
          },
        },
      },
      authenticating: {
        invoke: {
          id: "authenticateUser",
          src: 'authenticateUser',
          onDone: {
            target: "authenticated",
            actions: assign({ isAuthenticated: (context, event) => true }),
          },
          onError: {
            target: 'unauthenticated'
          },
        },
      },
      authenticated: {
        on: {
          LOGOUT: {
            target: "unauthenticated",
          },
        },
      },
    },
...

并发送AUTHENTICATE事件:

代码语言:javascript
复制
<button onClick={() => send("AUTHENTICATE")}>AUTHENTICATE</button>

此外,我建议完全避免使用isAuthenticated。您可以检查是否已使用方法进行身份验证。

代码语言:javascript
复制
<h3>
    isAuthenticated: {current.matches('authenticated') ? "True" : "False"}
</h3>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71390147

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档