未处理的网络错误 401 在使用 Apollo 反应本机和空 graphql 响应时

Unhandled Network Error 401 When using Apollo in react native & empty graphql response

我正在使用 create-react-native-app cli 构建一个 react-native 应用程序 这是我正在使用的软件包。除光纤外的所有最新稳定版 "dependencies": { "apollo-cache-inmemory": "^1.0.0", "apollo-client": "^2.0.1", "apollo-link": "^1.0.0", "apollo-link-error": "^1.0.0", "apollo-link-http": "^1.0.0", "expo": "^21.0.0", "graphql": "^0.11.7", "graphql-tag": "^2.5.0", "react": "16.0.0-alpha.12", "react-apollo": "^2.0.0", "react-native": "^0.48.4", "react-navigation": "^1.0.0-beta.15" }

应用运行正常,路由导航正常。我有两条路线,App 和 FeedList。

该应用程序与 github 图 api(我不知道 github 访问令牌是否 需要 ,如果需要,我已经添加了它,但我不知道这是不是正确的方法)

Feedlist 包装在 graphql HoC 组件中,它的道具有一个 data 已经填充了 graphql request 的结果(即使请求失败)

可以参考The structure of the data prop


应用组件

import React, { Component } from 'react'
import ApolloClient from 'apollo-client'
import { ApolloLink } from 'apollo-link'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { ApolloProvider } from 'react-apollo';
import { onError } from 'apollo-link-error';
import Router from './router'

class App extends Component {
  createClient() {
    const httpLink = createHttpLink({ uri: 'https://api.github.com/graphql'})

    // handle network error
    const errorLink = onError(({ networkError }) => {
        if (networkError.statusCode === 401) {
          console.log(networkError)
        }
      // let errorMessage = networkError.statusCode === 401 ? 'Network error 104, handled' : 'link sucess'
      // console.log(errorMessage, networkError)
    })

    // apply widdleware to add access token to request
    let middlewareLink =  new ApolloLink((operation, forward) => {
      operation.setContext({
        headers: {
          authorization: 'GITHUB_ACCESS_TOKEN'
        }
      })
      return forward(operation)
    })
    const link = middlewareLink.concat(httpLink)
    

    // Initialize Apollo Client with URL to our server
    return new ApolloClient({
    link: link,
    cache: new InMemoryCache(),
    })
  }
  render () {
    return (
      <ApolloProvider client={this.createClient()}>
        <Router />
      </ApolloProvider>
    )
  }
}

export default App


FeedList 组件

import React, { Component } from 'react';
import { Text } from 'react-native';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';

// The data prop, which is provided by the wrapper below contains,
// a `loading` key while the query is in flight and posts when ready
const FeedList = ({ data }) => {
  console.log(data) // returns default from HoC injected props
  console.log('FeedList Eroor!!',data.error) // returns undefined
  return data.error ? <Text> Error Fetching posts</Text>:<Text>fetching posts... </Text>
}

// The `graphql` wrapper executes a GraphQL query and makes the results
// available on the `data` prop of the wrapped component (PostList here)
export default graphql(gql`{
  search(type: REPOSITORY, query: "react", first: 20) {
    edges {
      node {
        ... on Repository {
          nameWithOwner
          owner {
            login
          }
        }
      }
    }
  }
}`, { options: { notifyOnNetworkStatusChange: true } })(FetchPost);

重要的部分是 Wrapped FeedList 组件,它记录来自 props 的数据和 App 组件内的 createClient() 方法。 我按照this尝试捕获数据请求过程中可能发生的错误。

HoC 包装器组件完成了它的工作,FeedList 的数据属性除了来自 api 的响应之外拥有一切。

注意这个错误不会让app崩溃

上图也显示了与 expo simulator on android

相同的错误消息

所以我想我的问题是

  1. 如何捕获错误? Here is a similar issue
  2. 如果这是我构建查询的方式,那就是问题所在。如何正确获取 github api 到 return 数据?

Here is the repo you can run and reproduce the error

注意Issue#1 in that repo is similar to this SO question and I have already fixed it by handling data.error as per the documentation

另请注意,大部分文档都是针对旧版本的 apollo-client > v2.x.x

Issue #2 正是我在这里要问的。感谢您的帮助

401 状态表示身份验证无效。正如您所猜到的,您需要一个有效的 OAuth 令牌来发送您的请求。出于开发目的,您可以 generate one. Make sure you include the scopes outlines as outlined here:

user
public_repo
repo
repo_deployment
repo:status
read:repo_hook
read:org
read:public_key
read:gpg_key

您不希望用户通过您的凭据访问 API,因此最终您需要在您的应用中实施 OAuth2 身份验证流程来为每个最终用户生成令牌。