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

Proposal: API changes to support multiple clients #464

Closed
1st8 opened this issue Feb 16, 2017 · 49 comments

Comments

Projects
None yet
@1st8
Copy link

commented Feb 16, 2017

Hey,

I would like to add support for multiple clients, similar to http://dev.apollodata.com/angular2/multiple-clients.html

Therefore I am proposing the following API changes and would like to have feedback before preparing a PR for this.

ApolloProvider

const ExtraProvider = createApolloProvider({ for: 'extraClient' })
// We could create the default ApolloProvider with createApolloProvider({ for: 'default' }) too
ReactDOM.render(
  <ApolloProvider client={client}>
    <ExtraProvider client={extraClient}>
      {...}
    </ExtraProvider>
  </ApolloProvider>,
  rootEl
)

graphql

New config key use to select the client to be used for the given statement.

// like before: uses the default client provided as "client" to execute given query
// new: uses client provided as "extraClient" to execute given specialQuery
export default compose(
  graphql(query),
  graphql(specialQuery, { use: 'extraClient' }),
)(Component);

Cheers!

@jbaxleyiii

This comment has been minimized.

Copy link
Member

commented Feb 16, 2017

I think this would be great!

@1st8

This comment has been minimized.

Copy link
Author

commented Feb 16, 2017

My mistake, this API is not possible (maybe there is a complicated solution), because childContextTypes has to be defined statically on ApolloProvider.

I will update my proposal to something that should work easier.

@1st8

This comment has been minimized.

Copy link
Author

commented Feb 16, 2017

I just pushed a work-in-progress commit, in case someone wants to see working code: 1st8@63c42db#diff-ff711df5e0aa7417faaf90767b79ac8bR35

Looking forward to get feedback. Cheers!

@calebmer

This comment has been minimized.

Copy link
Contributor

commented Feb 16, 2017

Instead of implementing a provideClient function, could you instead add functionality to the ApolloProvider component? So:

<ApolloProvider client={client} as="extraClient">
  {...}
</ApolloProvider>

I am curious, why would you want this feature? Also, why would this be better than passing a client instance directly to the graphql function? Like so:

export default graphql(MyQuery, {
  client: ...,
})(MyComponent);

…or if a subtree needed a different client rendering an <ApolloProvider> just for that subtree.

I would prefer just passing in clients directly for an initial implementation.

@1st8

This comment has been minimized.

Copy link
Author

commented Feb 17, 2017

Instead of implementing a provideClient function, could you instead add functionality to the ApolloProvider component?

This was exactly my first idea, which is afaik not possible, because the client would have to be passed down under a unique key in the context depending on the as prop.
Context keys have to be specified statically on the component, so I can't see a way to depend them on props, which makes sense to me.

What do you think of the following compromise that is somewhere between my HoC approach and your suggestion?

const ExtraProvider = createApolloProvider({ for: 'extraClient' })
// We could create the default ApolloProvider with createApolloProvider({ for: 'default' }) too
ReactDOM.render(
  <ApolloProvider client={client}>
    <ExtraProvider client={extraClient}>
      {...}
    </ExtraProvider>
  </ApolloProvider>,
  rootEl
)

I am curious, why would you want this feature

In my use-case I need to provide multiple clients to a subtree of the application [1] and additionally the endpoint url depends on state from previous parts of the application [2].

…or if a subtree needed a different client rendering an just for that subtree.

[1] => I need multiple clients present in the same subtree of my application, so ApolloProvider alone isn't an option

Also, why would this be better than passing a client instance directly to the graphql function?

[2] => I can't create the clients ahead of time to pass them to graphql, like you suggested

Imagine a screen where the user provides a hostname and based on that a session with multiple clients on different endpoints is started. The user can also go back and change the host.
Changing the infrastructure to use a single endpoint or host is not an option.

Hope that answers your questions and makes my requirements understandable 😄

@calebmer

This comment has been minimized.

Copy link
Contributor

commented Feb 17, 2017

This was exactly my first idea, which is afaik not possible, because the client would have to be passed down under a unique key in the context depending on the as prop. Context keys have to be specified statically on the component, so I can't see a way to depend them on props, which makes sense to me.

It’s possible. Just provide a map in context. We don’t need to put each client in a separate context key. So a context that looked like this:

const context = {
  apolloClients: {
    default: ...,
    foo: ...,
    bar: ...,
  },
};

The propType would be:

PropTypes.objectOf(PropTypes.instanceOf(ApolloClient))

Imagine a screen where the user provides a hostname and based on that a session with multiple clients on different endpoints is started. The user can also go back and change the host. Changing the infrastructure to use a single endpoint or host is not an option.

I still think there is a much smaller feature we could create which allows you to build the complex system you need on top of it rather than building the complexity of this specific use case into react-apollo.

What about allowing a user to pass a client into a component created with graphql as a prop in addition to context? So a graphql HOC would first check props for a client and if a client prop does not exist it would then check context for a client prop.

This would then allow you to implement a CustomApolloProvider component and a customGraphql function which gives you the exact behavior your application needs. How does that sound? 😊

@1st8

This comment has been minimized.

Copy link
Author

commented Feb 17, 2017

It’s possible. Just provide a map in context. We don’t need to put each client in a separate context key.

... and I could add more clients further down the component tree by mutating the map in the context? Is that a good idea or even legal?
I thought about this before, too, but stopped because I didn't want to mutate the context object.

What about allowing a user to pass a client into a component created with graphql as a prop in addition to context? So a graphql HOC would first check props for a client and if a client prop does not exist it would then check context for a client prop.

Give me some time to think about this. Right now it seems to me, that this would limit the number of usable clients for a given component to one. EDIT: Well I could still implement the use option on graphql, to tell it which prop to use, right? But then, why not use the context and avoid supplying the same prop on multiple levels.

Other than that, do you have any thoughts on my last code example?
I quite like it, because it just adds that little bit of needed flexibility to the existing idea.

@calebmer

This comment has been minimized.

Copy link
Contributor

commented Feb 17, 2017

... and I could add more clients further down the component tree by mutating the map in the context? Is that a good idea or even legal?
I thought about this before, too, but stopped because I didn't want to mutate the context object.

You would just clone the context and then you wouldn’t be mutating it.

const nextClientMap = { ...lastClientMap };

Give me some time to think about this. Right now it seems to me, that this would limit the number of usable clients for a given component to one.

Wouldn’t your approach have this limit too? Given that use is statically defined in the graphql HOC. By passing in client as a prop you could select a client to use with an options function, or could add the selection functionality to a customGraphql HOC.

Other than that, do you have any thoughts on my last code example?

Is it the one you linked above? I’m not in love with the design as I’ve mentioned before, and it may also break ApolloProvider’s alternative behavior as a Redux store provider by putting the store in default__store instead of just store 😣

@1st8

This comment has been minimized.

Copy link
Author

commented Feb 17, 2017

Is it the one you linked above?

No, I meant the one from #464 (comment)

But nevermind!

You would just clone the context and then you wouldn’t be mutating it.

const nextClientMap = { ...lastClientMap };

Shit, you're right! I thought reassignment was also forbidden, but you can of course just shadow the previous context.

So just to be safe, I will repeat your suggestion, which was also my initial idea.
Is this a change you would support?

// provide clients, which share the same store, but with different reducer keys
ReactDOM.render(
  <ApolloProvider client={client} store={store}>
    <ApolloProvider client={extraClient} as="extraClient" store={store}>
      {...}
    </ApolloProvider>
  </ApolloProvider>,
  rootEl
)

// use selected clients
export default compose(
  graphql(query),
  graphql(specialQuery, { use: 'extraClient' }),
)(Component);

I still see one smaller problem with this approach, which can be resolved later if necessary:
All clients would have to use the same store, with different reducer keys, right?
Because I would still pass down a single store in the context, to not break the behaviour you described above.
I think the store context attribute is a bit of bad design, because it collides with the redux store and is undocumented behaviour afaik.

@calebmer

This comment has been minimized.

Copy link
Contributor

commented Feb 17, 2017

Yeah, I’m concerned with the Redux collision as well. I would much prefer the solution I mentioned above where we allow you to pass in client as a prop. This would allow you to do whatever you want with context in userland.

@1st8

This comment has been minimized.

Copy link
Author

commented Feb 20, 2017

This would allow you to do whatever you want with context in userland.

That makes sense. I will try to implement the basics later this week.
Thanks for your feedback!

@stevewillard

This comment has been minimized.

Copy link

commented Feb 21, 2017

I am also interested in this feature. Roughly, here is how I got it to work.

I created my own provider, which just modifies the context (replace the client variable with a new client). That way all children of the tree will be scoped to a different GraphQL endpoint.

import { PropTypes, PureComponent } from 'react';
import ApolloClient, { createNetworkInterface } from 'apollo-client';

const clients = {};

export default class CustomProvider extends PureComponent {
  static propTypes = {
    children: PropTypes.node,
    uri: PropTypes.string.isRequired
  };


  static childContextTypes = {
    client: PropTypes.object
  };


  getChildContext = () => {
    const { uri } = this.props;

    let client = clients[uri];

    if (!client) {
      client = new ApolloClient({
        networkInterface: createNetworkInterface({
          uri,
          opts: {
            credentials: 'include'
          }
        })
      });


      clients[uri] = client;
    }


    return {
      ...this.context,
      client
    };
  }


  render = () => this.props.children;
}

Then, I just wrap components in this Provider which need a different client context:

<CustomProvider uri={'...'}>
    <MyComponent>
        ...
    </MyComponent>
</CustomProvider>

It definitely does some weird stuff with redux though. I think it it creates a Store each time a client is new'd up, although I haven't look too closely at the react-apollo internals to understand what's really going on.

Also, not to derail the thread, but this approach works with
"react-apollo": "0.10.1"

But in the latest version 0.11.2 I'm seeing some behavior where the children of my <CustomProvider /> aren't fetching their data from the custom endpoint (they're reusing old stale data). I think it has something to do with #462 but I'm not sure why yet. Any help would be greatly appreciated. For now, I'm stuck at version 0.10.1.

Official support (or at least documentation) for multiple clients would be great. I know it's a non-standard approach, and most people don't need this, but it fits my requirements really well, and makes the code quite elegant.

@calebmer

This comment has been minimized.

Copy link
Contributor

commented Feb 21, 2017

@stevewillard it may be good to open a new issue for the error you mention with #462

This is the kind of DIY approach I’d like to enable, however, with our implementation 👍

@stevewillard

This comment has been minimized.

Copy link

commented Feb 21, 2017

I'd like to open an issue, but I wanted to try to isolate the problem and create a small repo for it first. it's kind of hard to explain without seeing a full example.

@helfer

This comment has been minimized.

Copy link
Member

commented Feb 22, 2017

@1st8 @stevewillard I'm interested in the use-case that you guys have that requires multiple clients. I think there may be a better solution that we could implement in the future, like a special network interface / executor function.

@1st8

This comment has been minimized.

Copy link
Author

commented Feb 24, 2017

A custom network interface was also something that crossed my mind, but I discarded it in order to avoid cache/store conflicts, when running two identical queries against multiple endpoints.

@1st8

This comment has been minimized.

Copy link
Author

commented Feb 24, 2017

While I was looking into the props based approach I just found a commit removing exactly that: 626dbb7
Does anyone know what that was about?
It doesn't feel right wanting to reintroduce something via PR that was explicitly removed without deeper knowledge.

On the other hand: Would the updated proposal from my initial post stand a chance of being merged if it was submitted as PR?
It is my favourite, since it only slightly extends the current API and would give an easy way to support multiple clients without requiring everyone to DIY.

@jbaxleyiii

This comment has been minimized.

Copy link
Member

commented Feb 24, 2017

@1st8 we removed it to prevent accidental collisions from props that were named client (i.e. client="name of client" in a CRM application).

I think this could be best implement initially via @calebmer suggestion:

// added import for clarity
import MyOtherClient from "../other-client"

export default graphql(MyQuery, {
  client: MyOtherClient,
})(MyComponent);

@helfer this is a use case we are thinking through at NewSpring as we migrate our GraphQL endpoint from our js implementation to a dotnet one that is built into our CRM. We would like an incremental roll over to the new endpoint instead of a hard switch.

I think the store context attribute is a bit of bad design, because it collides with the redux store and is undocumented behaviour afaik.
@1st8, @calebmer the store prop is by design for use with a custom redux implementation http://dev.apollodata.com/react/redux.html#creating-a-store

fwiw, this is my preferred implementation design

// provide clients, which share the same store, but with different reducer keys
ReactDOM.render(
  <ApolloProvider client={client} /* client creates sanboxed redux store */>
    <ApolloProvider client={extraClient} as="extraClient" /* extraClient creates sanboxed redux store */ >
      {...}
    </ApolloProvider>
  </ApolloProvider>,
  rootEl
)

// use selected clients
export default compose(
  graphql(query),
  graphql(specialQuery, { use: 'extraClient' }),
)(Component);

SSR should just work thanks to @tmeasday's refactor to prevent context collisions, but we need to verify tests passing of course

@1st8 do you feel like you could implement this? Or do you want me to?

@1st8

This comment has been minimized.

Copy link
Author

commented Feb 24, 2017

Let me have a go at implementing it, seems we have everything together. 👍

Just to be clear:
Providing the clients like this does mean that I will have to change context.client to context.clients (or rather context.apolloClients?) and it becoming an Object, in order to merge multiple clients under one context key.
Would you be okay with the key becoming apolloClients? Could avoid other collisions in the future and is encapsulated anyway, so no changes to existing code necessary.

@jbaxleyiii

This comment has been minimized.

Copy link
Member

commented Feb 24, 2017

@1st8 I think sounds great!

@stevewillard

This comment has been minimized.

Copy link

commented Feb 24, 2017

@helfer My company, https://curio.org/ provides a way for people to upload, share and visualize datasets. It's the beginnings of a Github for data concept. We have a general GraphQL API (https://api.curio.org/graphql), but we also dynamically create GraphQL endpoints for each dataset (Curio) that you create. The schema is based off of what fields exist in the data and of what type.

When you navigate to a Curio page, I dynamically change the context (like in the example above), and issue a query:

query FetchFields {
  schema {
    field,
    types
  }
}

Which is basically our introspection query to get all the fields and the types for the current Curio. When you switch to a different Curio page, the context changes, and the same query gets re-issued.

I think the following would work for me, but it's a bit clunky:

graphql(specialQuery, { use: 'extraClient' }),

I guess I could make the 'use' keyword based off the URL params?

@calebmer

This comment has been minimized.

Copy link
Contributor

commented Feb 24, 2017

@stevewillard this is why I prefer a props based solution, or a solution that extends options to include a client:

graphql(query, {
  options: props => ({ client: ... }),
})(MyComponent)
@calebmer

This comment has been minimized.

Copy link
Contributor

commented Feb 24, 2017

I’m still opposed to the use/as semantics 😣 (but importantly not the idea of enabling multiple clients!). I think it’s a better idea to let that live in a community package. Here are my thoughts on the PR: #481 (comment)

@helfer

This comment has been minimized.

Copy link
Member

commented Feb 24, 2017

@stevewillard Oh, that's an interesting use-case. I think the disadvantage of using multiple clients that have different schemas is that it would become a lot more difficult to statically analyze queries. But since the endpoints are dynamically generated, I assume that the same would be the case for your queries, so it shouldn't be an issue.

Is there a reason it has to be multiple clients, or could it also be achieved with a smart network interface that knows which endpoint a query needs to be sent to? The answer to this question should come down to whether or not there could be naming collisions between the types in the two (or more schemas), and whether you can generate ids that are unique across schemas or not.

@stevewillard

This comment has been minimized.

Copy link

commented Feb 25, 2017

Nope, there's no reason that I need to use multiple clients. I'd be happy (probably happier) with a custom network interface. I originally thought about creating a network interface, but I wasn't sure how to structure it.

ids across schema will be unique, but the general structure (root queries, most fields) will be the same. Also, many types don't have ids at the moment :( As an example, for a dataset that a bunch of rows (items) about people, you might issue something like this:

items(limit: 3) {
    data {
      _id
      _source {
        email
        address
      }
    }
  }

But then the same-ish query could be executed for a different dataset about Hearthstone cards:

  items(limit: 3) {
    data {
      _id
      _source {
        durability
        description
        attack
        health
      }
    }
  }

(The takeaway here is that the _source type, and it's fields are dependent on which dataset your'e viewing)

It probably doesn't help that we don't follow a Relay-like convention for entities and connections, and we don't have ids for everything. I'm happy to restructure the API to be more accommodating, but the general feeling I have is that a custom network interface over multiple clients is preferable.

@calebmer

This comment has been minimized.

Copy link
Contributor

commented Feb 27, 2017

@stevewillard Could you have a custom network interface that executes against a GraphQL schema that nests different schemas at different levels?

For example:

{
  curio { item(limit: 3) { ... } }
  hearthstone { item(limit: 3) { ... } }
}

Something like this could easily be done using a GraphQL.js schema that lives in the client and not the server. Some pseudo-code:

import { GraphQLObjectType, buildClientSchema, print } from 'graphql';

const QueryType = new GraphQLObjectType({
  name: 'Query',
  fields: {
    curio: {
      type: buildClientSchema(curioIntrospectionJson),
      resolve: (source, args, context, { fieldNodes }) => {
        // Print a GraphQL query using just the sub-selection set for this field.
        // We will execute this query against the actual GraphQL schema it resolves to.
        const query = print({
          type: 'Document',
          definitions: [{
            type: 'OperationDefinition',
            operation: 'query',
            selectionSet: {
              type: 'SelectionSet',
              selections: fieldNodes.map(({ selectionSet }) => ({ type: 'InlineFragment', selectionSet })),
            },
          }],
        });
        return executeCurioGraphQLQuery(query);
      },
    },
    // Same for Hearthstone and other data sets...
  },
});

Then a network interface would look something like the network interface from react-apollo-error-template (the schema is defined with GraphQL.js as well).

I’d really love to see a dynamic architecture like this in production as it demonstrates the flexibility of GraphQL and the tooling that has been created around it.

@1st8

This comment has been minimized.

Copy link
Author

commented Mar 1, 2017

Thats a really interesting approach, never would have thought of building a schema like this in the client. I will play around with it and maybe it solves this whole multiple endpoints topic elegantly.

@stevewillard

This comment has been minimized.

Copy link

commented Mar 1, 2017

Yeah - I think that might work. I'll try it out later this week. Thanks :)

@stevewillard

This comment has been minimized.

Copy link

commented May 5, 2017

I never had a chance to implement exactly what what @calebmer was proposing, but I was able to successfully use the 1.x version of Apollo using a combination of changing the client context (as I mentioned earlier in this thread) for endpoint-specific Component trees, and also aliasing queries that are identical, but hit different endpoints.

I'm pretty happy with our current set up now. Thanks for making Apollo flexible enough to support this non-standard use case! I hope that if you guys decide to make schema introspection part of this client, that it'll be optional or flexible to support multiple clients / dynamic schemas.

@flexzuu flexzuu referenced this issue May 26, 2017

Merged

Add support for client in options #729

5 of 6 tasks complete
@raphaelcosta

This comment has been minimized.

Copy link

commented Jun 8, 2017

👍

@RSpace

This comment has been minimized.

Copy link

commented Jun 16, 2017

While we wait for proper multi client support, there's another hack you can use if you simply need use a different client in a child component:

class ParentComponent extends Component {
  static childContextTypes = {
    client: PropTypes.object.isRequired
  }

  getChildContext() {
    const client = new ApolloClient({
      networkInterface: createNetworkInterface({uri: OTHER_ENDPOINT_URL})
    })
    return { client }
  }

  render () {
    return <ChildComponent>
  }
}

Any graphql queries in ChildComponent and descended components will now go to OTHER_ENDPOINT_URL.

@stale stale bot added the wontfix label Jul 5, 2017

@stale

This comment has been minimized.

Copy link

commented Jul 5, 2017

This issue has been automatically marked as stale becuase it has not had recent activity. It will be closed if not further activity occurs. Thank you for your contributions to React Apollo!

@RSpace

This comment has been minimized.

Copy link

commented Jul 6, 2017

Bump. I still think this is highly needed.

@stale stale bot removed the wontfix label Jul 6, 2017

@stubailo

This comment has been minimized.

Copy link
Member

commented Jul 6, 2017

Looks like there was some progress just now! #729

@flexzuu

This comment has been minimized.

Copy link
Contributor

commented Jul 6, 2017

Yeah i implemented the proposed change. Let me know if you need help on how to use it in your app. I prepared some lib to use react-apollo with multiple apollo-clients. I plan to open source it as thin layer on top off react-apollo.

@RSpace

This comment has been minimized.

Copy link

commented Jul 6, 2017

@flexzuu Fantastic - thanks! I'll wait for the updated documentation from you, as it's a little unclear from the PR exactly how it works. The library you mention would off course be even better, so please do share :)

@jbaxleyiii

This comment has been minimized.

Copy link
Member

commented Jul 6, 2017

Released in 1.4.3! docs to come!

@jbaxleyiii jbaxleyiii closed this Jul 6, 2017

@micahlisonbee

This comment has been minimized.

Copy link

commented Dec 1, 2017

Are there docs on this yet? Looking but haven't found anything yet.

@vjpr

This comment has been minimized.

Copy link

commented Dec 11, 2017

@jbaxleyiii Are there docs on this? I could only find mention of it in the Apollo Angular docs https://www.apollographql.com/docs/angular/features/multiple-clients.html.

@stubailo

This comment has been minimized.

Copy link
Member

commented Dec 12, 2017

@vjpr here are the relevant types:

export interface MutationOpts<TVariables = OperationVariables> {
variables?: TVariables;
optimisticResponse?: Object;
updateQueries?: MutationQueryReducersMap;
refetchQueries?: string[] | PureQueryOptions[];
update?: MutationUpdaterFn;
client?: ApolloClient<any>;
notifyOnNetworkStatusChange?: boolean;
}
export interface QueryOpts<TVariables = OperationVariables> {
ssr?: boolean;
variables?: TVariables;
fetchPolicy?: FetchPolicy;
pollInterval?: number;
client?: ApolloClient<any>;
notifyOnNetworkStatusChange?: boolean;
// deprecated
skip?: boolean;
}

My understanding is that you can now pass client in the query options, like:

graphql(query, {
  options: {
    client: myClient
  }
})

Would you mind sending a PR to the docs? Probably here: https://www.apollographql.com/docs/react/basics/setup.html#graphql-config-options

@github0013

This comment has been minimized.

Copy link

commented Dec 24, 2017

For anyone who is still searching for how to use multiple clients, I did a repo for you.
https://github.com/github0013/multi-apollo-client/tree/master

@lfernando-silva

This comment has been minimized.

Copy link

commented Feb 21, 2018

@github0013 's solution works well!

@Frunez

This comment has been minimized.

Copy link

commented Mar 1, 2018

Are there docs to this yet? Can't find client option anywhere

@Jinnified

This comment has been minimized.

Copy link

commented Apr 9, 2018

ok, looks like you should be able to parse the client prop to query

const GoodDogsBrent = () => (
  <Query query={GET_DOGS} client={someApolloClient}>
    {({ loading, error, data }) => {
      if (error) return <Error />
      if (loading || !data) return <Fetching />

      return <DogList dogs={data.dogs} />
    }}
  </Query>
)
@Frunez

This comment has been minimized.

Copy link

commented Apr 9, 2018

Thanks, I figured it out and it's as you say, in my case I was importing a gql template query (apologies if my dev lingo is awful) and a config along with the query then exporting my component with the graphql function a bit like this, works quite well:

import { userClient } from './apolloClients'

const getQuery = gql`query userQuery(....)`

const queryConfig = {
  name: userData,
  options: {
    client: userClient,
  }
}

class ReactClass .... {.... return {props.userData.user}}; //skipped a lot of boilerplate here

export default graphql(getQuery, queryConfig)(ReactClass);

If I didn't define a client it would default to the one I set up in the provider.

@jrounsav

This comment has been minimized.

Copy link

commented May 16, 2018

I'm finding that this works for queries, but mutate calls are referencing the "default" endpoint rather than the one provided by under client.options.

Is anybody else seeing the same?
Ex. The following is being sent through compose()

graphql(GetQuery, {
      options: {
        fetchPolicy: "network-only",
        client: client2
      },
      props: (props) => ({ 
        survey: props.data.getSurvey,
      })
    });
/** ---- - - - -- - - - */
graphql(SubmitMutation, {
      options:{
        client: client2,
      },
      props: (props) => ({
        submit: submission => {
          props.mutate({
            variables: {
              ...submission
            },
          })
        }
      })
    });

Query pulls my data just fine, but on submission i'm finding that the mutation references the default client's endpoint.

line 117 of Mutation.tsx has this.client = context.client; while Query.tsx line 163 says this.client = props.client || context.client;

Would adding "props.client" be the way to go or am I just adding the client wrong?

@victorgb6

This comment has been minimized.

Copy link

commented Jun 4, 2018

Hi I'm having the same problem as @jrounsav, query works well but mutations don't. Did you were able to find the solution?

Thanks

@jrounsav

This comment has been minimized.

Copy link

commented Jul 1, 2018

@victorgb6
We weren't able to get it working. My group is using aws-appsync to handle our GQL backend though, and Amazon has done some stuff that wraps some of what react-apollo has going on in their own package so I'm wondering if that could be the culprit.

I don't suppose you're using AppSync as well?

@oosswwaalldd

This comment has been minimized.

Copy link

commented Feb 22, 2019

I have been working for this workaround with no problem:

ReactDOM.render( <ApolloProvider client={{ secureClient, pubClient }}> <App /> </ApolloProvider>, document.getElementById("root") )

and then back in my code I use
client.pubClient.mutate()
or
client.secureClient.mutate()

I come from Angular world and it was pretty easy to set up several clients but i cannot see that in React.

Let me know if this works for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.