xstate:如何将状态初始化为特定节点?

Posted

技术标签:

【中文标题】xstate:如何将状态初始化为特定节点?【英文标题】:xstate: how can I initialize the state to a specific node? 【发布时间】:2021-06-09 12:07:47 【问题描述】:

我有一个多步骤表单,基本上包含以下基本步骤:select services -> contact -> billing。当用户更改他们所在的步骤时,我会显示一个进度条并发出事件,这是我当前使用 xstate 的基本模式:

const formMachine = new Machine(
  id: 'form-machine',
  initial: 'selectService',
  context: 
    progress: 0,
    pathname: '/select-service',
  ,
  states: 
    selectService: 
      entry: assign(
        progress: 0,
        pathname: '/select-service',
      ),
      on: 
        NEXT: 'contact',
      
    ,
    contact: 
      entry: assign(
        progress: 1 / 3,
        pathname: '/billing'
      ),
      on: 
        PREVIOUS: 'selectService',
        NEXT: 'billing',
      
    ,
    // ... there's more actions but that's the gist of it
  
);

这是可视化:

在我的 React 组件中,我会查看此服务以了解 pathname 的变化,以便推送到历史记录

function SignupFormWizard() 
  const history = useHistory();
  const [state, send, service] = useMachine(formMachine);

  useEffect(() => 
    const subscription = service.subscribe((state) => 
      history.push(state.context.pathname);
    );
    return subscription.unsubscribe;
  , [service, history]);

  // ...

但是,问题是:每当我重新访问一条路线(例如,我直接导航到/billing)时,它都会立即将我带回/select-service。这对我的代码来说是有意义的,因为它会执行初始状态和订阅。

我将如何在特定节点初始化状态机?

【问题讨论】:

【参考方案1】:

useMachine 钩子接受第二个参数,它是一个配置对象。在这个对象中,您可以使用state 键设置状态,但您必须自己构建状态,它看起来像这样:

let createdState = State.create(stateDefinition);
let resolvedState = formMachine.resolve(state);
let [state, send, service] = useMachine(formMachine, state: resolvedState);

在我看来,当您需要 restore persisting state 时,它很有效,但是从头开始手动创建 stateDefinition 实在是太麻烦了。

您可以做的是创建初始状态并选择您想要实际开始的位置:

initial: 
  always: [
    
      target: "selectService",
      cond: "isSelectServicePage",
    ,
    
      target: "contact",
      cons: "isContactPage",
    ,
    
      target: "billing",
      cond: "isBillingPage",
    ,
  ],

然后,当你启动你的机器时,你所要做的就是设置初始上下文值:

let location = useLocation();
let [state, send, service] = useMachine(formMachine, 
  context:  pathname: location.pathname ,
);

【讨论】:

以上是关于xstate:如何将状态初始化为特定节点?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法使用从 Firebase 返回的承诺来初始化 Xstate 状态机?

如何将二维数组的所有元素初始化为java中的任何特定值

如何防止 XState 节点在接收事件时重置其子并行状态?

(重新)将向量初始化为具有初始值的特定长度

有没有办法在 useEffect 的反应组件中设置 xstate 机器的状态?

实验3