Search code examples
javascriptreactjsxstate

unable to restore state machine with persisted state using xstate and react


I am trying to create a state machine which can persist the machine's state details at any given point in time and then restore the machine with the persisted state and context values on revisiting the page. The Xstate docs mention about persisting data and rehydration using the local storage but I am unable to do so. I have made a sandbox link to try and replicate the issue. Can someone help or guide me on what I may be doing wrong?

Thanks in advance

Codesandbox link: https://codesandbox.io/s/green-snow-ortw6?file=/src/App.js


Solution

  • You must pass the persisted state the first time that you invoke to useMachine, do not forget that useMachine is a closure, in that way it will work, for instance

    import { useMachine } from "@xstate/react";
    import { createMachine } from "xstate";
    import { optionsConfig } from "./machine/machineDefinition";
    import { machineConfig } from "./machine/machineDefinition";
    import "./styles.css";
    const machine = createMachine(machineConfig, optionsConfig);
    
    export default function App() {
      const [state, notifyMachine] = useMachine(machine, {
        state: JSON.parse(localStorage.getItem("per_ste"))
      });
      const { context, value } = state;
    
      const onNextClick = () => {
        notifyMachine("NEXT");
      };
    
      const onPrevClick = () => {
        notifyMachine("BACK");
      };
    
      const onEventAClick = () => {
        notifyMachine("SEND_BUTTON_CLICKED", { data: "A" });
      };
    
      const onEventBClick = () => {
        notifyMachine("SEND_BUTTON_CLICKED", { data: "B" });
      };
      const onLogContextButtonClick = () => {
        console.log("CONTEXT:", context.eventTriggeredList);
      };
      const onLogStateButtonClick = () => {
        console.log("CONTEXT:", value);
      };
    
      const onPersistClick = () => {
        localStorage.setItem("per_ste", JSON.stringify(state));
      };
      const onRehydrateClick = () => {
        const persistedState = localStorage.getItem("per_ste");
        const parsedState = JSON.parse(persistedState);
        setPersistedState(parsedState);
      };
    
      return (
        <div className="App">
          <h1>Step Machine</h1>
          <h3>Start clicking to see some magic happen!</h3>
          <h2>{`Current Step: ${context.currentStepIndex}`}</h2>
          <div>
            <button onClick={onNextClick}>NEXT</button>
            <button onClick={onPrevClick}>PREV</button>
            <button onClick={onEventAClick}>SEND EVENT A</button>
            <button onClick={onEventBClick}>SEND EVENT B</button>
          </div>
          <br />
          <div>
            <button onClick={onLogContextButtonClick}>console Events</button>
            <button onClick={onLogStateButtonClick}>console Current State</button>
          </div>
          <br />
          <br />
          <div>
            <button onClick={onPersistClick}>PERSIST STATE</button>
            <button onClick={onRehydrateClick}>REHYDRATE STATE</button>
          </div>
        </div>
      );
    }