---
# System prepended metadata

title: State Management with xstate

---

# State Management with xstate

- Objective:
    - it needs to be run on both platform (RN and Web)

- Questions:
    - Network
        - 
    - App State / Global State
        - We need to have a grasp of how the application actually works
        - Currently, we don't have a model to know what application are doing
            - We already have pattern to make sure this is the case. But the debugging experience is not as good as it should (is it necessary?)
        - Problems of this current appoach, we need lot of effort to know exactly what is being consumed by our app
    - UI State
        - 
    - Do we need to use the same tools to manage state and network state?
        - In our case, we already use [React Query]() 
        - For global state, we already use [Zustand]()

## Current Approach
- Pros
    - We have already dedicated tools to do very specific job. And they are doing really well
        - [React Query]() for network state
        - [Zustand]() for global state

    -  Much more simpler to use
        -  Functionality is a big plus for specific tools [React Query]()
            -  Refetch Functionality
            -  Cache 
            -  Window Focus (Refeching)
            -  `let {isLoading, error, data} = useQuery(key, promise)`
            -  Developer Experience is great
            -  Network API is a big plus

    - Zustand is improvement over React Context
        - Much simpler to use
        - It's already baked with selector. No rerender for non-related component
- Cons
    - [React Query]() SSR Story is not good
        - Singleton object for data
        - user -> asking for page -> ssr -> put the data to react query -> check the stale status -> it's stale -> giving empty object -> client think that the data is stale -> refetch
            - Client not doing SSR
            - SSR Failed  
        - SSR is not sharable
            - ```ts
               import {hydrate} from 'react-query';

               // hydrate :: 'data => Omit<data, "updedDate">;
 
               async function getServerSideProps() {
                let data = await getData();
                  return {props: {
                     data: hydrate(data);
                  }}
               }
                ```
           - in turns that the `etag` generated by the server is always different. If we have a case like the client need to validate the data, it always failed because etag always different from the last time. 
        - Zustand SSR [link](https://github.com/pmndrs/zustand/issues/182)
        - 
            

## Model

```ts
let userMachine = createMachine({
  context: {
    user: null
  },
  initial: 'idle',
  states: {
    idle: {
      invoke: {
        src: 'fetchUserData',
        onSuccess: 'data',
        onError: 'error'
      }
      on: {
        FETCH: {target: 'loading'}
      }
    },
    loading: {
       on: {
          SUCCESS: {target: 'data'}
       }
    },
    data: {
      on: {
         
      }
    }
  }
}, {
   services: {
     fetchUserData: () => {
        
     }
   }
})
```

```ts 

function UserProfileRoute(props) {
   let user = useActor(userMachine(initial: )).withContext({
     user: props.user
   })
}

async function getServersideProps() {
  let user = await fetchUserData();
  return {
    props: {
      user
    }
  }
}
```

```ts 
// const: visual editor?
let userMachine = (initial, user) => createMachine({
  context: {
    user: null
  },
  initial: initial,
  states: {
    idle: {
      tag: 'watiting'
      invoke: {
        src: 'fetchUserData',
        onSuccess: 'data',
        onError: 'error'
      }
      on: {
        FETCH: [
        {cond: (ctxt) => ctx.user ? true: false, target: 'data'}
      ]
    },
    loading: {
       tag: 'loading',
       on: {
          SUCCESS: {target: 'data'}
       }
    },
    data: {
      on: {
         
      }
    }
  }
}, {
   services: {
     fetchUserData: () => {
        
     }
   }
})

// abstract this away from user 
state.tags("loading") => <Loading Component />
state.context.user && state.tags("data") => <Data />

// 
let data = 
```

### Explore
- Xstate Modelnya gimana?
    - context
    - zustand 
    - redux
- Pattern
    - File and Folder Structure
    - 

## SSR 
 - context?
     - ssr story?
 - boilerplate?
     - network?

## References
- [xstate with redux](https://github.com/mattpocock/redux-xstate-poc)
- [xstate context](https://github.com/coder/coder/tree/main/site/src/xServices)
- [RFC](https://github.com/statelyai/rfcs/blob/davidkpiano/0002-system-receptionist/text/0000-system-receptionist.md)
- 