react-apollo-hooks
react-apollo-hooks copied to clipboard
Add second returned value to useMutation ?
WIth the Mutation component from Apollo. you can do something like this:
const AddTodo = () => {
let input;
return (
<Mutation mutation={ADD_TODO}>
{(addTodo, { data }) => (
<div>
<form
onSubmit={e => {
e.preventDefault();
addTodo({ variables: { type: input.value } });
input.value = "";
}}
>
<input
ref={node => {
input = node;
}}
/>
<button type="submit">Add Todo</button>
</form>
</div>
)}
</Mutation>
);
};
could the useMutation hook be modified like so?
const [doMutation, { data, loading, error }] = useMutation(...);
@cvburgess I don't follow how and why are you using data in that example. Can you elaborate more or fix the example?
Yeah I'm not sure about data (maybe that's the response data for doing optimistic updates?), but loading and error would be extremely helpful.
Sorry, I pasted that right from the Apollo Docs.
I personally use loading and errors more than data but all three are returned (like <Query />)
The main use cause is for showing a loading state while waiting for a response (like in a form). Optimistic update is a fantastic alternative, but sometimes you need to be "honest" about the loading state (or errors).
The useMutation is pretty much just call to client.mutate which alone does not provide loading/error prop. Looking at the Mutation component it handles it on its own by utilizing promises. Should be fairly easy to implement with hooks.
It will be a breaking change, so it should be done rather sooner than later, but it will certainly simplify component rendering a lot.
One thing to consider, should it rethrow error similarly to queries? #28
I am going to give a stab at this right now. Just saying in case someone else has the same idea :)
@cvburgess Have a look at the PR ☝️
@FredyC the data prop is also useful in case you don't want to update the respective queries but still need to know the result of the mutation. this use case is what actually brought me to this issue.
an alternative would be to wait to the mutation itself to finish mutation().then({ data }) => ...) but because of optimistic responses, the promise resolves with the optimistic data rather than the response one.
would you consider including the data prop in the PR you linked above?
i guess another approach is to remove the optimistic response for the mutations that need the actual result (and then just wait for mutation to resolve like described above)
Um, but there is data included in the PR :) There is also a called prop, that I didn't even know existed on the Mutation component. As I said in the PR, it's pretty much copy of that component.
@FredyC That work (and this whole process) have been really fantastic.
Thank you for the fast, quality work and the inclusive atmosphere!
Makes sense to me that useMutation would follow the Mutation component API rather than following the client.mutate API.
This is react-apollo-hooks, so parity should be sought with react-apollo (which means react-apollo components) and not just apollo-client.
Instead of breaking change there could be just an additional API.
This would be a great feature. At the risk of being thumbs downed, maybe call it useMutationWithState to avoid a breaking change? I know its more typing and perhaps not intuitive, but breaking changes are really annoying. Just my two cents.
Before 1.0.0 it is allowed to have breaking changes per SemVer so I don't see what the problem is. Current version is 0.4.5, so just merge this and publish as 0.5.0. npm update won't bump to that version, so if there are people angry when they manually upgrade then they don't know semver or they don't read changelogs. That's their problem.
@kirill-konshin @jwickens You always have to account with breaking changes when using bleeding edge tech. That's just the price of getting hands on some cool stuff :) But in this case, it's a really tiny change, basically, you just wrap the returning value to []. For someone well-versed with regexp, it could surely be done automatically with find&replace.
Hey folks, have been using react-apollo-hooks for a new project & I agree that this is an essential feature - really glad that this is being added to the 0.5.0. release (as mentioned in #138).
As I'm a bit impatient (/ wanted the API in one of my components asap) I hacked together this simple hook, which should roughly have the same API as implemented in #135. Just wanted to share it in case it could be useful to anyone else.
import { ApolloError } from 'apollo-client'
import { useState } from 'react'
import { MutationFn } from 'react-apollo'
import { useMutation } from 'react-apollo-hooks'
interface MutationResult {
data?: any
error?: ApolloError
called: boolean
loading: boolean
hasError: boolean
}
const initialState = (): MutationResult => ({
data: undefined,
error: undefined,
called: false,
loading: false,
hasError: false,
})
// this should be unnecessary once https://github.com/trojanowski/react-apollo-hooks/pull/135 lands
// see https://github.com/trojanowski/react-apollo-hooks/issues/138
export function useFutureMutation(
doc: any,
options?: any
): [MutationFn<any, any>, MutationResult] {
const [result, setResult] = useState<MutationResult>(initialState)
const mutate = useMutation(doc, options)
const futureMutate: MutationFn<any, any> = async options => {
setResult({ ...initialState(), called: true, loading: true })
try {
const { data, errors } = await mutate(options)
const hasError = errors != null
setResult({
...result,
data,
error: hasError
? new ApolloError({ graphQLErrors: errors })
: undefined,
loading: false,
hasError,
})
return data
} catch (error) {
setResult({
...result,
error,
loading: false,
hasError: true,
})
}
}
return [futureMutate, result]
}
You can use it wherever you use useMutation, eg.:
// before
const mutate = useMutation(gql`...`, { variables: {...} })
// after
const [mutate, { data, error, called, loading, hasError }] = useFutureMutation(gql`...`, { variables: {...} })
Obviously the types could use improving, but that's already tackled in the 'real' implementation - it should hopefully be an easy drop-in once it lands.
(btw, minor nitpick about the API in #135 - hasError is not defined in react-apollo's MutationResult, normally we'd just use error != null as check for an error condition. Might make sense to use react-apollo's MutationResult type for 'full compatibility'/'future mergeability')
cc #93 for visibility
Well, if anyone is really impatient, I have a #93 published under the @speedlo/react-apollo-hooks. It includes the wrapping of error objects which @trojanowski ditched. It's already released as 1.0.0 because it's being used in a production of 3 apps and it is indeed stable.
However, I am not promising any kind of support (issue reporting is disabled). The source sits at master branch of https://github.com/fredyc/react-apollo-hooks. Also, docs are not updated properly 😊
I personally don’t mind breaking changes of bleeding edge components ) not sure about all the others.
I just published an alpha version of 0.5.0 with #135 merged-in. It's available as react-apollo-hooks@alpha.
Thanks a lot @trojanowski! Have tried out react-apollo-hooks@alpha & it seems to work great :)
I confirm. Works like charm with no changes on graphql-code-generator level.
Is this still only in alpha or why is the issue still opne?