houdini icon indicating copy to clipboard operation
houdini copied to clipboard

Add way to toggle between isolated and global stores

Open AlecAivazis opened this issue 3 years ago • 2 comments

In order to support situations where a user wants to SSR a component query (or for some other reason interact with a store), we need to support a distinction between "isolated" and "global" stores. At the moment, all routes gets a local instance of a store but this clearly doesn't work for preloading store values on the server.

// 1
export const GQL_User = factory()

// 2
export const UserStore = factory

// 3
export default GQL_User

AlecAivazis avatar Jul 18 '22 08:07 AlecAivazis

I would like to write the doc for this feature first. I think it can help elaborate. Then we can have some reviews from different people and decide how to move forward? In the end, as we will have opt-in/out at a different level, we will have great flexibility. That's why I think that the doc will be key.

Of course, things will evolve from this original attempt! 😅


Store Modes

Stores have two modes: Isolated or Global, and you can configure the mode of each store at different levels: 1/ Globally in houdini.config.js that will apply to all your stores.

{
  storeMode: 'Isolated' | 'Global'
}

2/ On each individual store, you can overwrite the behavior and specify the mode

query MyQuery @Isolated | @Global { # @config(mode= 'Isolated' | 'Global')  ???
  id
  name
}

Isolated mode

This mode is designed to have local stores, your data will be contained in a defined space.

A typical use case: You have a component <Users> having one query getUsers with some args like old: Boolean To display the two components at the same time, you want your mode to be isolated so that they are independent.

<Users old={true}>
<Users old={false}>

Different syntax can ba used:

<!-- preprocessor -->
<script>
  import { graphql, query } from '$houdini'
  
  const { data } = query(graphql`query getUsers ( ... ){ ... }`)
</script>

{JSON.strignify($data, null, 2)}
<!-- inline Document -->
<script>
  import { graphql } from '$houdini'

  const store = graphql`query getUsers ( ... ){ ... }`
    
  $: browser && store.fetch()
</script>

{JSON.strignify($store.data, null, 2)}
<!-- external document                 query getUsers ( ... ){ ... } -->
<script>
  import { getUsersStore } from '$houdini'
  
  const store = getUsersStore()
  
  $: browser && store.fetch()
</script>

{JSON.strignify($store.data, null, 2)}

Houdini is exporting isolated stores like this:

// 1 => Not available in Isolated mode
// export const GQL_Users = factory()

// 2
export const UsersStore = factory

// 3 => Not available in Isolated mode
// export default GQL_Users

// 4
export default UsersStore

Global mode

This mode is designed to share stores globally across components/application. You will have access to the same store everywhere.

A typical use case: You have a component <ActiveTodos> having one query activeTodos If you put the component on a page, you will not get SSR. To enable SSR, you can go on the Route where it's displayed and call a fetch on this global store.

<ActiveTodos>
<!-- In the route -->
<script context="module">
  import { GQL_activeTodos } from '$houdini';

  export async function load(event) {
    await GQL_activeTodos.fetch({ event });
    return {};
  }
</script>

Houdini is exporting global stores like this:

// 1 
export const GQL_activeTodos = factory()

// 2 => Not available in Global mode
// export const activeTodosStore = factory

// 3
export default GQL_activeTodos

// 4 => Not available in Global mode
// export default activeTodosStore

Now, it's time to comment & co. 👍

jycouet avatar Jul 18 '22 22:07 jycouet

With @AlecAivazis, we would be happy to have feedback from the community. As you saw, we want to support both. One question would be, what should be the default behavior?

In your code, what would you use mostly? (vote here 👇) 🎉 Isolated 🚀 Global ❤️ I don't know, but I'm sure you will figure it out 😅 I just give you strength ^^


Notif for people who already contributed: @pixelmund @fehnomenal @ledesmablt @SorenHolstHansen @alexlafroscia @ximus @ZerdoX-x @oplik0 @david-plugge @rmarscher @benbender @georgecrawford @jbruxelle @B2o5T @lukaszwisniewski88 @notrab @richarddavenport @avarun42 @scottBowles @cya @Giovannini @happycollision

I don't plan to spam you non-stop, no worries. Thank you

jycouet avatar Jul 20 '22 09:07 jycouet

I'm going to close this to keep it tidy. the store model has drastically changed since this issue was opened and I think it needs to be refined a bit more to accommodate the fact that ALL stores are now isolated since they are instantiated in load

AlecAivazis avatar Oct 22 '22 04:10 AlecAivazis