首页 > 解决方案 > 使用 apollo-link-error 显示错误 toast

问题描述

我试图用 显示一个 toast/snackbar apollo-link-error,但是当我这样做时,错误 toast 反复出现而没有停止,并且加载时显示的加载器在后台旋转。

ui中的多个错误消息

我的阿波罗客户端包含此代码...

const errorLink = onError(handleErrors)

const httpLink: ApolloLink = createHttpLink({
  uri: graphqlUri,
})

const link = ApolloLink.from([errorLink, authLink, httpLink])

handleErrors函数在我的 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
  )

然后传入 ApolloProvider。useToasts钩子来自react -toast-notifications

我之前正在处理组件中的错误...

const { loading, data, error } = useQuery(Query)

if (error) return <div>{error.message}</div>

但是已经从使用切换graphql-yogaapollo-server后端,因此必须以不同的方式处理错误。

如果我删除了 toast 通知,而只是打印到控制台,它就可以正常工作。为什么我的 toast 被重复创建,我怎么能只显示一个错误?

谢谢。

标签: reactjsreact-hooksapollo-clientapollo-server

解决方案


您可能已经找到了解决方案,但此示例答案可能对其他人有用。

注意:此答案未使用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>


推荐阅读