Generalized wizard state restore / resumption #82
-
Hey there! Getting more into XSW, I find myself wondering if there's a pattern for restoring the state of a wizard, e.g., if someone gets logged out mid-fill. Maybe not for the current field, but for past states, for instance. Any thoughts/examples appreciated! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
There is @mahmoud ! You can see the There are 2 vars and 3 methods on the
Here's a quick snippet of code for how I've done this in the past (chopping out lines of code for readability and focusing on the session callbacks). Also, before calling things "wizards" I was calling them interviews. I'd like to be consistent by just calling everything a wizard: export const WizardRunner = (props) => {
const { data: user } = useLoggedInUser();
return (
<WizardRunner
configExitTo={props.configExitTo ?? "/journey"}
debugConfig={{
logging: true,
skipSaves: user.isAdmin,
}}
models={upsolveWizardModelsMap}
spellMap={preparedSpellMap}
sessionEnabled={props.sessionEnabled ?? false}
sessionForceNew={
// hack: for webdriver tests, we ensure we're getting a fresh session
props.sessionForceNew || window?.___FORCE_NEW_WIZARD_SESSION___
}
sessionRequestCheck={async ({ key, version }) => {
const wizardSession = await axios
.get("/v1/wizardSession/check", {
params: {
machineId: key,
machineVersion: version,
userId: user.id,
},
})
.then((res) => res.data?.wizardSession);
return wizardSession?.id ? wizardSession : null;
}}
sessionRequestStart={async ({ key, version }) => {
const wizardSession = await axios
.post("/v1/wizardSession/start", {
wizardSession: {
machineId: key,
machineVersion: version,
userId: user.id,
},
})
.then((res) => res.data?.wizardSession);
return wizardSession;
}}
sessionRequestProgress={async ({ wizardSessionId, machine, progressPercentage }) => {
await axios.put(`/v1/wizardSession/progress`, {
wizardSession: {
machineContext: machine.context,
machineState: machine.value, // cancel/save states should still be saved. we won't init from sessions w/ these machineStates
id: wizardSessionId,
endedAt: machine.done ? new Date() : undefined,
progressAt: new Date(),
},
progressPercentage,
});
}}
/>
);
}; One key detail about the backend is how you want to handle your session check. I use the Thought I had this an example, but definitely can add one! Will call it |
Beta Was this translation helpful? Give feedback.
There is @mahmoud ! You can see the
TWizardSession
type for details here. The XState machine's context has a specific schemaTCreateMachineContext
for tracking internal changes as the person goes through the form. This is what gets modified overtime, what you'll have access to in the methods below so you can persist to a db, and then what you can load back in. Under the hood it's being passed in the plain old XState createMachine method.There are 2 vars and 3 methods on the
<WizardRunner />
top level component you'll want to use in combination with backend endpoints to persist to a session (aka machine context with a schema) to the database:sessionEnabled
: true/false for whether we run…