apollographql / apollo-client

:rocket:  A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.
https://apollographql.com/client
MIT License
19.38k stars 2.66k forks source link

client.extract() seems not working with Reactive Variables #6713

Open Melzmr opened 4 years ago

Melzmr commented 4 years ago

UPD: Found out that cache with reactive variables doesn't extract() from the apollo client during the SSR rendering. It is always empty object after extracting.

Hello!

Thanks for your work on AC3. I am so excited to use its new API especially Reactive Variables.

I tried to implement it into my project that has SSR enabled.

The server renders fine and responds with the following cache object:

window.__APOLLO_STATE__ = {
  "ROOT_QUERY": {
    "__typename": "Query",
    "isLoggedIn": true
  }
}

Then on the client, I am trying to populate my client cache object with the state from the server.

const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        isLoggedIn() {
          return isLoggedInVar();
        },
      },
    },
  },
}).restore(window.__APOLLO_STATE__);

Also, I should create reactive variable with the following construction:

export const isLoggedInVar = makeVar(*initialValue*);

The problem is I must provide initialValue for the Reactive Variable and that initialValue will overwrite the value that has come from the server. Basically if I do cache.readQuery({...}) right after restoring the state isLoggedIn would be set to true until I use cache with reactive variables.

I can still use readQuery and writeQuery in my project and everything will be fine, but Reactive Vars seem so easy to use and less boilerplate.

The question is: is it possible to use reactive variables with the cache that is restored from server?

Thanks!

P.S. I am using the latest stable release of AC: 3.0.2. LMK I need to provide more info.

reducio commented 4 years ago

I have same problem with Next.js, all changes doing in client side part, after hydration. I set value of reactive variable in cache in first component and try change value this reactive variable in second component, but value not changed. If change variable in current component I have reactivity.

jlramosr commented 3 years ago

Yeah! I have the same problem. Something new about this?

dipiash commented 3 years ago

I have the same problem with Next.js. I use getServerSideProps for initialize apollo client store. But data for reactive vars reset on client. I get a hydration error with that data not the same.

Hi, @benjamn! Can you help with it if it possible?

UPD: Now I see only two ways to solve my problem fast:

  1. Rewrite part of app on read/writeQuery (only wrappers)
  2. or use getInitialProps / getServerSideProps for populating data from server and for reactive var initialisation by the same data on client and server. For example:

    // baseRVD.ts
    export const reactiveVarData = makeVar(!isServer() ? window?.__NEXT_DATA__?.props?.reactiveVarData : reactiveVarData)
    
    // _app.tsx
    ...
    const HOC = function (Child: NextPage<AppProps>) {
      return class Higher extends React.Component {
        static async getInitialProps(ctx: NextPageContext) {
          if (isServer()) {
            console.info(isServer())
          } else {
            // eslint-disable-next-line no-underscore-dangle
            console.info(window.__NEXT_DATA__.props)
          }
    
          const props = await Child.getInitialProps(ctx)
    
          props.data = {
            one: 'one',
            two: 'two',
          }
    
          userDataExperiment(props.data)
    
          return props
        }
    
        render() {
          // eslint-disable-next-line @typescript-eslint/ban-ts-comment
          // @ts-ignore
          return <Child {...this.props} />
        }
      }
    }
    
    ...