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 状态机?