0

我正在开发一个 UI 项目,该项目通过共享上下文处理状态更新,与此处描述的非常相似

const {appState, dispatch} = useContext(AppContext);

对于某些组件,我不会通过 xstate 来玩弄状态机。

const SomeComponent = () => {
  const {appState, dispatch} = useContext(AppContext);
  const [state,send,service] = useMachine(MyComponentStateMachine);
}

现在,理想情况下,我希望我的状态机在进入状态时调度某些事件。但是,状态机获取我的 AppContext 的最佳方式是什么?

目前,我正在处理组件本身的这个事件调度,观察状态机的状态并在它进入某个状态时根据需要调度一个事件:

const SomeComponent = () => {
  const {appState, dispatch} = useContext(AppContext);
  const [state,send,service] = useMachine(MyComponentStateMachine);

  useEffect(() => service.subscribe(state => {
     if(state.value == "Some relevant state of MyComponentStateMachine")
       dispatch({type: SomeEvent, arg: 12345});  
    }).unsubscribe, [service]);
}

这很好用,但它给我的印象是糟糕的设计。我认为直接从状态机而不是从组件分派这个事件会更干净。

状态机有什么好的方法来获取 AppContext 吗?

简单地为状态机创建一个工厂方法,将调度作为参数并保留它是否明智?

4

1 回答 1

0

我相信在那里调用你的调度函数没有错。由于您正在使用上下文,因此您将无法在机器内部调用调度,除非您将函数作为参数传递。你可以试试看,不知道行不行。

(您可以使用操作来触发事件或状态更改的副作用)

在这种情况下,它会是这样的:

<pre>
  //Component
  const SomeComponent = () => {
    const { appState, dispatch } = useContext(AppContext);
    const [ state, send ] = useMachine(MyComponentStateMachine);

    useEffect(() => {
      if(state.matches("stateName")) {
        const data = { type: SomeEvent, arg: 12345 };
        send("EVENT_NAME", { callback: dispatch, data })
      }
    }, [state]);
  }


  //Machine
  const MyComponentStateMachine = Machine({
    ...
    states: {
      stateName: {
        on: {
          EVENT_NAME: "secondState",
        },
      },
      secondState: {
        entry: ["actionName"]
      }
    },
    {
      actions: {
        actionName: (ctx, e) => {
          e.callback(e.data);
        },
      }
    }
  });
</pre>

*** 还要看看我是如何比较状态的,这是读取状态值的一种更简洁的方法。此外,如果您已经在使用 useMachine 钩子,则无需订阅该服务,如果状态发生变化,该钩子将触发组件重新渲染。

于 2021-02-12T22:23:22.430 回答