Reputation: 1653
I'm trying to show a toast/snackbar with apollo-link-error
, but when I do the error toast shows up repeatedly without stopping, and the loader that shows on loading spins in the background.
My apollo client contains this code...
const errorLink = onError(handleErrors)
const httpLink: ApolloLink = createHttpLink({
uri: graphqlUri,
})
const link = ApolloLink.from([errorLink, authLink, httpLink])
where the handleErrors
function is passed in in my App.tsx...
const { addToast } = useToasts()
const handleErrors: ErrorHandler = ({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
const errors = graphQLErrors.map(({ message }) => message)
addToast(errors.join(`, `))
}
if (networkError) console.log(`[Network error]: ${networkError}`)
}
const client = apolloClient(
token,
GRAPHQL_URI,
handleErrors
)
and then passed into the ApolloProvider. The useToasts
hook comes from react-toast-notifications.
I was previously handling the errors in the component...
const { loading, data, error } = useQuery(Query)
if (error) return <div>{error.message}</div>
but have switched from using graphql-yoga
to apollo-server
on the backend and so am having to handle errors differently.
If I remove the toast notification, and just print to the console instead, it works fine. Why are my toasts being created repeatedly and how can I just show one on error?
Thanks.
Upvotes: 1
Views: 2538
Reputation: 543
You might have find the solution, but this sample answer might be useful for other people.
NOTE: This answer not using react-toast-notification
import React, { useState, useContext } from 'react'
import ApolloClient from 'apollo-boost'
const ErrorContext = React.createContext([])
const ErrorProvider = () => {
const [errors, setError] = useState([])
const handleUpdateError = error => {
setError([...errors, error])
}
const ctx = { handleUpdateError }
return (
<ErrorContext.Provider value={ctx}>
{errors.map(errorMessage => <Toast>{errorMessage}</Toast>)}
{children}
</ErrorContext.Provider>
)
}
class ApolloCustomProviderWithContext extends React.Component {
construtor(props) {
super(props)
const { handleUpdateError } = props
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
const errors = graphQLErrors.map(({ message }) => message)
handleUpdateError(errors.join(','))
}
})
const httpLink = createHttpLink({ uri: "/graphql" });
this._client = new ApolloClient({
link: errorLink.concat(httpLink),
cache: new InMemoryCache(),
})
}
render () {
return <ApolloProvider client={this._client}>{this.props.children}</ApolloProvider>
}
}
const ApolloCustomProvider = props => {
const { handleUpdateError } = useContext(ErrorContext)
return (
<ApolloCustomProviderWithContext handleUpdateError={handleUpdateError}>
{props.children()}
</ApolloCustomProviderWithContext>
)
}
const Application = () => {
return (
<ErrorProvider>
<ApolloCustomProvider>
{children}
</ApolloCustomProvider>
// Your Application Code
</ErrorProvider>
)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Upvotes: 1
Reputation: 181
Hard to tell without seeing the code as a whole but it seems to be adding a new Toast per render of your component,
You should check how and where this is being called, my guess this is nothing to do with apollo and something to do with rerendering of the component
Also toasts are generally a list that gets added to so it will just grow and grow instead of replacing
Upvotes: 0