React Native、GraphQL、Apollo - 突变期间抛出的错误

Posted

技术标签:

【中文标题】React Native、GraphQL、Apollo - 突变期间抛出的错误【英文标题】:React Native, GraphQL, Apollo - Error thrown during mutation 【发布时间】:2017-10-25 05:03:40 【问题描述】:

我正在开发一个以 Apollo 客户端和 GraphQL 作为后端的 React Native 项目。我遇到的问题是,当我使用突变注册新用户时,我得到了用户已创建的肯定响应,但我也得到了一个错误,说 Error catch: TypeError: Cannot read property '未定义的变量

我不确定问题是什么,或者为什么返回错误。代码如下:

'use strict'

import React,  Component  from 'react';
import  Text, View, StyleSheet, AsyncStorage, Modal, TouchableHighlight  from 'react-native'
import  Actions, ActionConst  from 'react-native-router-flux'
import  Button  from 'react-native-elements'

// Apollo and GraphQL Packages
import ApolloClient,  graphql, withApollo  from 'react-apollo'
import gql from 'graphql-tag'
import  filter  from 'graphql-anywhere'
import  connect  from 'react-redux'
import Auth0Lock from 'react-native-lock'

// Styling Packages
import LinearGradient from 'react-native-linear-gradient'
import EStyleSheet from 'react-native-extended-stylesheet'

// View Packages
import ViewContainer from './ViewContainer'

// Auth0 Credentials
const clientId = "XXXX"
const domain = "XXXX"

// Props Declaration
type Props = 
  client: ApolloClient,
  createUser: (
    variables: 
      idToken: string,
      name: ?string,
      email: ?string
    
  ) =>  id: string


class Login extends Component 
  _lock: Auth0Lock
  props: Props

  constructor(props) 
    super(props)
    this._lock = new Auth0Lock(
      clientId: clientId,
      domain: domain,
      useBrowser: true
    )
  

  _showLogin() 
    this._lock.show(
      closable: true,
      connections: ['Username-Password-Authentication']
    , async (err, profile, token) => 
      if (!err) 
        AsyncStorage.setItem('token', token.idToken)
          .then(() => 
            this.props.client.resetStore()
          )
        this.props.createUser(
            variables: 
              idToken: token.idToken,
              name: profile.name
              email: profile.email
            
          )
          .then((data) => 
            console.log("Data received: " + data)
            Actions.registration( type: ActionConst.REPLACE )
          )
          .catch((err) => 
            console.log("Error caught: " + err)
            AsyncStorage.removeItem('token')
              .then(() => this.props.client.resetStore())
            // Actions.home( type: ActionConst.REPLACE )
          )
       else 
        console.log(err)
      
    )
  

  render() 
    return(
      <LinearGradient colors=['#34E89E', '#0F3443'] style=styles.linearGradient>
        <ViewContainer style=styles.viewContainer>
          <Button
            small
            raised
            buttonStyle= styles.button
            color="#fff"
            title="Login"
            onPress=() => this._showLogin() />
        </ViewContainer>
      </LinearGradient>
    )
  


const styles = EStyleSheet.create(
  viewContainer: 
    flex: 1,
    paddingTop: 70,
    paddingLeft: 20,
    paddingRight: 20
  ,
  linearGradient: 
    height: '$height',
  ,
  logo: 
    fontFamily: 'LiberatorHeavy',
    fontSize: 52,
    alignSelf: 'center',
    marginBottom: 400,
    color: 'white',
    backgroundColor: 'transparent'
  ,
  button: 
    backgroundColor: '#222222'
  
);

const createUserMutation = gql`
mutation createUser($idToken: String!, $name: String, $email: String) 
  createUser(
    authProvider: 
      auth0: 
        idToken: $idToken
      
    ,
    name: $name,
    email: $email
  )
    id
  
`

export default withApollo(
  graphql(createUserMutation,
     name: 'createUser' 
  )(Login))

【问题讨论】:

你确定这个错误特别来自这个组件吗?我会尝试的一件事是在 if 语句中打印出“this.props”,因为“this”在错误的范围内可能很危险,因为它的值是在运行时确定的 是的,我确定这是引发错误的组件 - 特别是这一行:.catch((err) =&gt; console.log("Error caught: " + err) 另外,通过开发控制台,我可以看到正确的变量正在传递,所以它成功了。我无法弄清楚为什么在我从服务器获得成功响应后它会抛出错误。 这个错误意味着某些东西正在搜索 x.variables 并且 x 为空。似乎唯一调用变量的时间是在突变中。你能检查一下查询是否错误地触发了两次,第二次没有传递变量? @mstorkson 你是对的 - 它出于某种原因发射了两次,尽管我仍然不确定为什么。将其更改为在 AsyncStorage.setItem('token'...) 中包含 createUser 有效。它只触发了一次并返回了积极的响应。我不是 100% 确定为什么会发生这种情况,但至少它现在有效。感谢您的帮助 没问题,很高兴能帮上忙 【参考方案1】:

所以错误是

createUser(variables...)

函数被触发两次,导致在变量被清除后抛出错误。我将代码更改为:

_showLogin() 
    this._lock.show(
      closable: true,
      connections: ['Username-Password-Authentication']
    , async (err, profile, token) => 
      if (!err) 
        AsyncStorage.setItem('token', token.idToken)
          .then(() => 
            this.props.client.resetStore()

            // Create user function was put in to AsyncStorage function to stop function from running twice. (Not sure why that was happening)
            this.props.createUser(
                variables: 
                  idToken: token.idToken,
                  name: profile.name,
                  email: profile.email
                
              )
              .then((data) => 
                console.log("Data received: " + data)
                Actions.registration( type: ActionConst.REPLACE )
              )
              .catch((err) => 
                console.log("Error caught: " + err)
                AsyncStorage.removeItem('token')
                  .then(() => this.props.client.resetStore())
                // Actions.home( type: ActionConst.REPLACE )
              )
          )
       else 
        console.log(err)
      

这解决了问题,我得到了正确的响应,尽管我仍然不确定为什么它在 Async 函数之后运行了两次。

如果有人有任何想法,请告诉我!

【讨论】:

以上是关于React Native、GraphQL、Apollo - 突变期间抛出的错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 Relay + React Native (create-react-native-app) 时出错:GraphQL 验证错误`未知类型“查看器”。`

仅返回选定字段 React Native / GraphQL / Amplify

无法在 GraphQL 突变中传递数组 - React Native

我如何在 react-native 聊天应用程序中使用 GraphQl 订阅从 GraphQl 查询中获取实时更新

React Native 上的 GraphQL Apollo 类型生成

使用 graphql 在 react-native 中重新获取查询