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

Use client from props in Mutation component #1890

Merged
merged 6 commits into from
Jun 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
- Adjust `getDataFromTree` to properly traverse React 16.3's context API
provider/consumer approach.
[PR #1978](https://github.com/apollographql/react-apollo/pull/1978)
- An `ApolloClient` instance can now be passed into a `Mutation`
component via a prop named `client`. This prop will override
an `ApolloClient` instance set via `context`, by the `ApolloProvider`
component.
[PR #1890](https://github.com/apollographql/react-apollo/pull/1890)

### 2.1.5

Expand Down
27 changes: 15 additions & 12 deletions src/Mutation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export interface MutationProps<TData = any, TVariables = OperationVariables> {
) => React.ReactNode;
onCompleted?: (data: TData) => void;
onError?: (error: ApolloError) => void;
client?: ApolloClient<Object>;
context?: Record<string, any>;
}

Expand Down Expand Up @@ -113,8 +114,13 @@ class Mutation<TData = any, TVariables = OperationVariables> extends React.Compo
constructor(props: MutationProps<TData, TVariables>, context: any) {
super(props, context);

this.verifyContext(context);
this.client = context.client;
this.client = props.client || context.client;
invariant(
!!this.client,
'Could not find "client" in the context or props of Mutation. Wrap ' +
'the root component in an <ApolloProvider>, or pass an ApolloClient ' +
'instance in via props.',
);

this.verifyDocumentIsMutation(props.mutation);

Expand All @@ -134,16 +140,20 @@ class Mutation<TData = any, TVariables = OperationVariables> extends React.Compo
nextProps: MutationProps<TData, TVariables>,
nextContext: MutationContext,
) {
if (shallowEqual(this.props, nextProps) && this.client === nextContext.client) {
const { client } = nextProps;
if (
shallowEqual(this.props, nextProps) &&
(this.client === client || this.client === nextContext.client)
) {
return;
}

if (this.props.mutation !== nextProps.mutation) {
this.verifyDocumentIsMutation(nextProps.mutation);
}

if (this.client !== nextContext.client) {
this.client = nextContext.client;
if (this.client !== client && this.client !== nextContext.client) {
this.client = client || nextContext.client;
this.setState(initialState);
}
}
Expand Down Expand Up @@ -269,13 +279,6 @@ class Mutation<TData = any, TVariables = OperationVariables> extends React.Compo
}.`,
);
};

private verifyContext = (context: MutationContext) => {
invariant(
!!context.client,
`Could not find "client" in the context of Mutation. Wrap the root component in an <ApolloProvider>`,
);
};
}

export default Mutation;
47 changes: 47 additions & 0 deletions test/client/Mutation.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,53 @@ it('updates if the client changes', done => {
mount(<Component />);
});

it('uses client from props instead of one provided by context', () => {
const link1 = mockSingleLink({
request: { query: mutation },
result: { data },
});
const client1 = new ApolloClient({
link: link1,
cache: new Cache({ addTypename: false }),
});

const link2 = mockSingleLink({
request: { query: mutation },
result: { data: data2 },
});
const client2 = new ApolloClient({
link: link2,
cache: new Cache({ addTypename: false }),
});

let count = 0;

mount(
<ApolloProvider client={client1}>
<Mutation client={client2} mutation={mutation}>
{(createTodo, result) => {
if (!result.called) {
setTimeout(() => {
createTodo();
});
}

if (count === 2) {
expect(result).toEqual({
loading: false,
called: true,
data: data2,
});
}

count++;
return <div />;
}}
</Mutation>
</ApolloProvider>,
);
});

it('errors if a query is passed instead of a mutation', () => {
const query = gql`
query todos {
Expand Down