Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Commit

Permalink
Refactor ApolloProvider/ApolloConsumer implementation to use React 16…
Browse files Browse the repository at this point in the history
….3 context API

The old way of passing the context still exists side-by-side with the new way to allow gradual migration of <Query>, <Mutation> and other modules that access the context in the "old" way.

This should unlock "user space" experiments with react hooks and react-apollo because if yoou want to access the context(client) in a hook, the context has to be exposed using the "new" context API

closes #1937
  • Loading branch information
vovacodes committed Oct 26, 2018
1 parent 76c930f commit b3e70c7
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 59 deletions.
69 changes: 21 additions & 48 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,13 @@
"zen-observable-ts": "0.8.10"
},
"dependencies": {
"@types/memoize-one": "^3.1.1",
"fbjs": "^1.0.0",
"hoist-non-react-statics": "^3.0.0",
"invariant": "^2.2.2",
"lodash.flowright": "^3.5.0",
"lodash.isequal": "^4.5.0",
"memoize-one": "^4.0.2",
"prop-types": "^15.6.0"
}
}
20 changes: 14 additions & 6 deletions src/ApolloConsumer.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import ApolloClient from 'apollo-client';
import ApolloContext from './ApolloContext';

const invariant = require('invariant');

export interface ApolloConsumerProps {
children: (client: ApolloClient<any>) => React.ReactElement<any> | null;
}

const ApolloConsumer: React.StatelessComponent<ApolloConsumerProps> = (props, context) => {
invariant(
!!context.client,
`Could not find "client" in the context of ApolloConsumer. Wrap the root component in an <ApolloProvider>`,
);
const ApolloConsumer: React.StatelessComponent<ApolloConsumerProps> = (props) => {
return (
<ApolloContext.Consumer>
{(context) => {
if (!context || !context.client) {
throw new Error(
`Invariant violation. Could not find "client" in the context of ApolloConsumer. Wrap the root component in an <ApolloProvider>`
);
}

return props.children(context.client);
return props.children(context.client);
}}
</ApolloContext.Consumer>
);
};

ApolloConsumer.contextTypes = {
Expand Down
11 changes: 11 additions & 0 deletions src/ApolloContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createContext } from 'react';
import ApolloClient from 'apollo-client';
import { DocumentNode } from 'graphql';


export interface ApolloContextValue {
client?: ApolloClient<Object>;
operations?: Map<string, { query: DocumentNode; variables: any }>;
}

export default createContext<ApolloContextValue | undefined>(undefined);
18 changes: 13 additions & 5 deletions src/ApolloProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as PropTypes from 'prop-types';
import { Component } from 'react';
import ApolloClient from 'apollo-client';
import { DocumentNode } from 'graphql';
import memoizeOne from 'memoize-one';
import ApolloContext, { ApolloContextValue } from './ApolloContext';

const invariant = require('invariant');

Expand All @@ -11,6 +13,11 @@ export interface ApolloProviderProps<TCache> {
children: React.ReactNode;
}

const memoizedGetChildContext = memoizeOne((client: ApolloClient<Object>): ApolloContextValue => ({
client: client,
operations: (client as any).__operations_cache__,
}));

export default class ApolloProvider<TCache> extends Component<ApolloProviderProps<TCache>> {
static propTypes = {
client: PropTypes.object.isRequired,
Expand Down Expand Up @@ -42,13 +49,14 @@ export default class ApolloProvider<TCache> extends Component<ApolloProviderProp
}

getChildContext() {
return {
client: this.props.client,
operations: (this.props.client as any).__operations_cache__,
};
return memoizedGetChildContext(this.props.client);
}

render() {
return this.props.children;
return (
<ApolloContext.Provider value={memoizedGetChildContext(this.props.client)}>
{this.props.children}
</ApolloContext.Provider>
);
}
}

0 comments on commit b3e70c7

Please sign in to comment.