Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apollo Link Context doesn't work on Apollo Client 2.5 #4533

Closed
ralphchristianeclipse opened this issue Mar 4, 2019 · 17 comments
Closed

Apollo Link Context doesn't work on Apollo Client 2.5 #4533

ralphchristianeclipse opened this issue Mar 4, 2019 · 17 comments

Comments

@ralphchristianeclipse
Copy link

The context is empty on the resolvers for Apollo Client 2.5 local state management

Any workarounds?

@hwillson hwillson self-assigned this Mar 4, 2019
10xjs added a commit to sensu/web that referenced this issue Apr 16, 2019
apollo-client v2.5 deprecates apollo-link-state and integrates client state resolvers as a core features of apollo-client. Unfortunately it doesn't provide a solution for customizing the apollo-link context provided to the resolvers as is possible with apollo-link-state.

(documented here: apollographql/apollo-client#4533)

Signed-off-by: Neal Granger <neal@nealg.com>
10xjs added a commit to sensu/web that referenced this issue Apr 16, 2019
apollo-client v2.5 deprecates apollo-link-state and integrates client state resolvers as a core features of apollo-client. Unfortunately it doesn't provide a solution for customizing the apollo-link context provided to the resolvers as is possible with apollo-link-state.

(documented here: apollographql/apollo-client#4533)

Signed-off-by: Neal Granger <neal@nealg.com>
@veeramarni
Copy link

Any update on this issue?

@ralphchristianeclipse
Copy link
Author

Same any updates?

@veeramarni
Copy link

I have verified with 2.5 version, I see context is working.

    client.mutate({
      mutation: Save,
      variables: {
        resource,
        value: 'test',
        options: {},
      },
      context: {
        apolloClient: client,
      },
    });

In the resolver, i can see the context that i passed.

@ralphchristianeclipse
Copy link
Author

I have verified with 2.5 version, I see context is working.

    client.mutate({
      mutation: Save,
      variables: {
        resource,
        value: 'test',
        options: {},
      },
      context: {
        apolloClient: client,
      },
    });

In the resolver, i can see the context that i passed.

But you have to manually pass the context.

I'm using vue-apollo it will probably work to modify the prototype of the apollo class .mutate function.

@barbieri
Copy link

Since the @client moved to be built-in and not a link anymore it created a different code path, while the Server executes through the link:

https://github.com/apollographql/apollo-client/blob/master/packages/apollo-client/src/core/QueryManager.ts#L1160

The client query completely ignores the context, calling runResolvers() directly:
https://github.com/apollographql/apollo-client/blob/master/packages/apollo-client/src/core/QueryManager.ts#L1170

I'll try to find out how to fix this

@hwillson hwillson removed their assignment Aug 7, 2019
@ralphchristianeclipse
Copy link
Author

This has been partially fixed using the defaultOptions which helps me removed apollo-link-state and apollo-link-context

but the problem is there is no way to set this up as a function.

  const defaultContext = {
    ctx,
    ...context,
    auth: window.owner
  };


  const client = new ApolloClient({
    cache,
    link: links,
    connectToDevTools: isDev,
    queryDeduplication: true,
    resolvers,
    // typeDefs,
    assumeImmutableResults: true,
    defaultOptions: {
      query: {
        context: defaultContext
      },
      watchQuery: {
        context: defaultContext
      },
      mutate: {
        context: defaultContext
      }
    }
  });

any thoughts?

@ralphchristianeclipse
Copy link
Author

Another problem is the link pipeline doesn't seem to work with the local stage management

for example apollo-link-logger doesn't log anything when doing client queries

@barbieri
Copy link

Another problem is the link pipeline doesn't seem to work with the local stage management

for example apollo-link-logger doesn't log anything when doing client queries

the >=2.5 code has special case for @client that doesn't run the link, this is a problem because you can't get the context, you can't have your error handlers to run, you can't do all that you usually do with the usual link chain :-(

@ralphchristianeclipse
Copy link
Author

@barbieri Thanks for that. maybe a hook or function that will run the link pipeline which would be optional for the dev to put in on the ApolloConfig

@barbieri
Copy link

@ralphchristianeclipse I'm not sure what motivated the specific handling, but in my experience it's worse than handling as link, you miss flexibility on how how to handle errors (ie: we use onError to append some to local state and show in the UI, we put the environment configuration in the context...)

@ralphchristianeclipse
Copy link
Author

@barbieri this works initially on the defaultOptions but there are some parts that the context is not available. I hope this gets a simple solution.

@ralphchristianeclipse
Copy link
Author

@barbieri

the resolution i've done is to wrap it in a function.

export const createContextResolver = resolver => {
  console.log(resolver);
  return (root, args, context, info) => {
    console.log(context);

    return resolver(
      root,
      args,
      { ...context, ...context.client.context },
      info
    );
  };
};

and then use it on my resolvers like this.

import { createContextResolver } from '../../utils/resolver';
const mapObject = (object, reducer) =>
  Object.fromEntries(Object.entries(object).map(reducer));
const mapValue = callback => ([key, value]) => [key, callback(value, key)];
const createContextResolvers = object =>
  mapObject(
    object,
    mapValue(value =>
      typeof value === 'object'
        ? mapObject(value, mapValue(value => createContextResolver(value)))
        : createContextResolver(value)
    )
  );
const resolvedTypes = createContextResolvers(types);
console.log(resolvedTypes);

and then on the client you just put up a context property there.

  const defaultContext = {
    ...ctx,
    ...context,
    auth: getAuth()
  };
 const client = new ApolloClient({ ...options })
 client.context = defaultContext;

@ralphchristianeclipse
Copy link
Author

Or you can put it up as a function

export const createContextResolver = (resolver, key) => {
  console.log(resolver, key);
  return (root, args, context, info) => {
    const newContext = Object.assign(
      context,
      typeof context.client.context === 'function'
        ? context.client.context()
        : context.client.context
    );
    return resolver(root, args, newContext, info);
  };
};

and use it like this

 client.context = () => defaultContext;

@barbieri
Copy link

yeah, we use something like that, however we have a reducer to wrap all the resolver methods of a given object

@veeramarni
Copy link

I'm stuck as well, trying to find a better way to pass additional details to context so that they can be accessible in the resolver.

@veeramarni
Copy link

#4533 (comment)

@ralphchristianeclipse Is this a workaround still only the option to feed the context? I want to find a way to load the context after the apollo client initializes but not through the hooks for every query and mutation.

@hwillson
Copy link
Member

A lot of the Apollo Client internals have changed since v3 was launched. We recommend trying a more modern version of @apollo/client. Let us know if you're still encountering this issue. Thanks!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants