error Policy in Apollo Client React does'nt work - graphql

I have aproblem when test Apollo.When I try query with apollo and graphql, i want response return error and partical data, so I set property errorPolicy:'all'. But its not work. I don't no why? Help please!
Here my code:
query { animal {
name
age }, school {
name
numberfd } } `
const { loading,data,error} = useQuery(GET_DASHBOARD_DATA, {
errorPolicy:'all',
onCompleted: (res) => {console.log("complete",res)},
onError : (res,data) => {console.log("ERRRR",res,data)},
})
and i want to receive:
{
error:[...], data:[animal:[...]] }
but its only response error.Here is Apollo's doc: https://www.apollographql.com/docs/react/data/error-handling/

onError type is onError?: (error: ApolloError) => void;. You don't have data inside onError callback.
After useQuery you can add:
console.log('data', data)
console.log('error', error)

I faced the same issue with errorPolicy: 'all', I only received the partial result inside onCompleted callback of useQuery, but no errors.
I created an ErrorLink like this:
private createErrorLink = () => {
return new ApolloLink((operation, forward) => {
return forward(operation).map((response) => {
// filter out errors you don't want to display
const errors = filterSomeErrors(response.errors);
if (errors && response?.data) {
response.data.errors = errors;
}
return response;
});
});
};
Now inside my onCompleted callback I get my data as well as errors. You will have to tweak your types a bit, because seems there is no errors field on response.data by default.
Mind that if you use onError from Apollo and return something from the link, it will retry your request containing errors!

Related

How to handle Apollo Graphql query error in Vue.JS?

I am using Vue.js with Vue-Apollo and trying to fetch shared member list using query. I am using the graphQL service in backend.
I am using apollo 'error' function to handle GraphQL error. When the request is made with invalid input, I can see the errors in the network tab, I can see the JSON for the custom errors messages. But I can't console the errors in 'error' function.
Here is the apollo query that is used to fetch shared member list -
apollo: {
sharedMembers: {
query: gql`
query item($uuid: ID) {
item(uuid: $uuid) {
...itemTemplate
members {
...member
permission
}
}
}
${ITEM_TEMPLATE}
${MEMBER}
`,
variables() {
return {
uuid: this.$route.params.uuid,
}
},
update(data) {
return data.item.members
},
error(error) {
console.log('errors', error)
}
},
},
The network response I got -
network_error
Using graphQLErrors
You could get the errors by looking in the error object for graphQLErrors:
error(error) {
console.log('errors', error.graphQLErrors)
}
or
error({ graphQlErrors }) {
console.log('errors', graphQLErrors)
}
Using apollo-error-link
You can use apollo-error-link to help solve your problem if the above doesn't work, docs here.
Here's an example from the docs and I added to it in the networkErrors section to show what you can do to edit the error message you see in your error block, or catch block if its a mutation.
import { onError } from "apollo-link-error";
const link = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) {
// Add something like this to set the error message to the one from the server response
networkError.message = networkError.result.errors[0].debugMessage
console.log(`[Network error]: ${networkError}`)
};
});
And then in your code:
error(error) {
console.log('error-message', error.message)
}
The console should then log your debugMessage from the server.
unfortunately i couldn't find out how i'd handle errors in such of graphql method call, but as an option you could provide onError method to ApolloClient constructor options. first argument is the error object. hopefully it may help. like so..
const apolloClient = new ApolloClient({
uri: 'http://localhost:4000',
onError(err) {
console.log(err)
},
})

Nuxt.js and Laravel Api - 422 Displaying Error instead of Forms

[Error][1]
Hi Team,
Whenever I am receiving the error return from laravel the nuxt.js project displays the error on the page instead the HTML/Forms. How can i handle this.
Here is my php code
return response()->json([
'errors' => [
'email' => ['Sorry we cant find you with those details.'],
],
], 422);
Javascript
async submit() {
await this.$auth.loginWith("local", {
data: this.form
})
In your JavaScript you need to wrap your await promise inside a try catch block. Here's a fix for your JS.
try {
await this.$auth.loginWith("local", {
data: this.form
})
} catch (e) {
return;
}
This is an old question at this point, but I thought I'd post the full code since I was pretty stumped and didn't find many great answers out there:
async handleSubmit() {
try {
const authResponse = await this.$auth.loginWith('local', {
data: this.formData
});
const { status, data } = authResponse;
if (status === 200)
this.createFlashAlert({ 'success': 'Login successful' });
} catch (error) {
if (error.response.status === 422)
this.createFlashAlert(error.response.data);
}
}
So the checklist:
Wrap the login call in a try/catch if you're using async await syntax (be sure to make it an async function i.e. async handleSubmit.
in the catch block, use the error.response object, this is an axios thing. With this you'll be able to access the response status and data.
If you log just the error object, it's not obvious that you can access the response within that error which is what had me stumped.

302 Found on Laravel in GET request made by cross-fetch on react

I have a component with a table, when this component mounts I would like to make a request to get data that fills the table.
In my table component:
componentDidMount() {
const { fetchTransactions } = this.props;
fetchTransactions()
}
This came from (I'm using redux):
const mapDispatchToProps = dispatch => ({
fetchTransactions: value => dispatch(fetchTransactions())
})
And the action:
export function fetchTransactions() {
return function (dispatch) {
dispatch(requestTransactions())
return fetch('/getTransactions')
.then(
response => response.json(),
error => console.log('An error occurred.', error)
)
.then(json => dispatch(receiveTransactions(json)))
}
}
When the component mounts, the action is dispatched and the fetch too, but the response is a 302 found as you can see here:
Using the browser it work as I expect:
Any ideas? thank you.

Observable from Subject

I'm trying to create actions from updates from a RX Subject
It's working but I get the error below.
Here is my Epic
export function uploadSceneFile(action$, store) {
return action$.ofType(CREATE_SCENE_SUCCESS)
.mergeMap(({payload}) =>
UploadSceneWithFile(payload)
.subscribe(res => {
if (res.progress > 0)
store.dispatch(uploadSceneProgress(res))
else if(res.progress === -1){
store.dispatch(uploadSceneSuccess(res))
requestSceneProcessing(res).map(res => {
})
}
})
)
}
And here is the Subject
export function UploadSceneWithFile(scene){
const subject$ = new Subject()
const uploader = new S3Upload({
getSignedUrl: getSignedUrl,
uploadRequestHeaders: {'x-amz-acl': 'public-read'},
contentType: scene.file.type,
contentDisposition: 'auto',
s3path: 'assets/',
onError:()=>subject$.next('error'),
onProgress: (val)=> subject$.next({...scene,progress:val}),
onFinishS3Put: ()=>subject$.next({...scene,progress:-1}),
})
uploader.uploadFile(scene.file)
return subject$
}
I read from a previous post that I'm supposed to be using .map, not .subscribe but nothing happens if I don't subscribe (the upload doesn't happen)
What's the best way of doing this?
subscribeToResult.js:74 Uncaught TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at Object.subscribeToResult (subscribeToResult.js:74)
at MergeMapSubscriber../node_modules/rxjs/operators/mergeMap.js.MergeMapSubscriber._innerSub (mergeMap.js:132)
at MergeMapSubscriber../node_modules/rxjs/operators/mergeMap.js.MergeMapSubscriber._tryNext (mergeMap.js:129)
at MergeMapSubscriber../node_modules/rxjs/operators/mergeMap.js.MergeMapSubscriber._next (mergeMap.js:112)
at MergeMapSubscriber../node_modules/rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
at FilterSubscriber../node_modules/rxjs/operators/filter.js.FilterSubscriber._next (filter.js:89)
at FilterSubscriber../node_modules/rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
at Subject../node_modules/rxjs/Subject.js.Subject.next (Subject.js:55)
at createEpicMiddleware.js:60
at createEpicMiddleware.js:59
at SafeSubscriber.dispatch [as _next] (applyMiddleware.js:35)
at
The problem is that you subscribe inside mergeMap and return a Subscription which is invalid. The callback needs to return only Observable, Promise, Array, or Iterable.
I'm not sure what exactly you need to do but if you need to perform some side-effects you can use do() operator instead of subscribing.
export function uploadSceneFile(action$, store) {
return action$.ofType(CREATE_SCENE_SUCCESS)
.mergeMap(({ payload }) => UploadSceneWithFile(payload)
.do(res => {
...
})
)
}
Or it looks like you could put do after mergeMap as well:
export function uploadSceneFile(action$, store) {
return action$.ofType(CREATE_SCENE_SUCCESS)
.mergeMap(({ payload }) => UploadSceneWithFile(payload))
.do(res => {
...
});
}

Apollo client mutation error handling

I'm using GraphQL and mongoose on the server.
When a validation error occurs the GraphQL mutation sends a response with status code 200. On the client side the response looks like this:
{
"data": null,
"errors": [{
"message": "error for id...",
"path": "_id"
}]
}
I would like to get access to the validation error using the catch functionality of the apollo-client mutation promise. Something like:
this.props.deleteProduct(this.state.selectedProductId).then(response => {
// handle successful mutation
}).catch(response => {
const errors = response.errors; // does not work
this.setState({ errorMessages: errors.map(error => error.message) });
});
How can this be done?
The previous answer from #stubailo does not seem to cover all use cases. If I throw an error on my server side code the response code will be different than 200 and the error will be handled using .catch() and not using .then().
Link to the issue on GitHub.
The best is probably to handle the error on both .then() and .catch().
const { deleteProduct } = this.props;
const { selectedProductId } = this.state;
deleteProduct(selectedProductId)
.then(res => {
if (!res.errors) {
// handle success
} else {
// handle errors with status code 200
}
})
.catch(e => {
// GraphQL errors can be extracted here
if (e.graphQLErrors) {
// reduce to get message
_.reduce(
e.graphQLErrors,
(res, err) => [...res, error.message],
[]
);
}
})
Note: This answer (and arguably the whole question) is now outdated, since mutation errors show up in catch in more recent versions of Apollo Client.
GraphQL errors from the mutation currently show up in the errors field on the response inside then. I think there's definitely a claim to be made that they should show up in the catch instead, but here's a snippet of a mutation from GitHunt:
// The container
const withData = graphql(SUBMIT_REPOSITORY_MUTATION, {
props: ({ mutate }) => ({
submit: repoFullName => mutate({
variables: { repoFullName },
}),
}),
});
// Where it's called
return submit(repoFullName).then((res) => {
if (!res.errors) {
browserHistory.push('/feed/new');
} else {
this.setState({ errors: res.errors });
}
});
Using graphql tag notation, yo have access to errors:
<Mutation mutation={UPDATE_TODO} key={id}>
{(updateTodo, { loading, error }) => (
<div>
<p>{type}</p>
<form
onSubmit={e => {
e.preventDefault();
updateTodo({ variables: { id, type: input.value } });
input.value = "";
}}
>
<input
ref={node => {
input = node;
}}
/>
<button type="submit">Update Todo</button>
</form>
{loading && <p>Loading...</p>}
{error && <p>Error :( Please try again</p>}
</div>
)}
</Mutation>
https://www.apollographql.com/docs/react/essentials/mutations.html

Resources