访问查询返回对象的 id 字段将其更改为未定义

Posted

技术标签:

【中文标题】访问查询返回对象的 id 字段将其更改为未定义【英文标题】:Accessing id field of query returned object changes it to undefined 【发布时间】:2019-05-04 08:34:07 【问题描述】:

我正在开发一个 react/mondgodb/graphql/apollo Web 应用程序。我设置了一个查询来使用 fbid 获取成员(它是我插入为 fbid 的 firebase Id,以便通过 firebase id 在我的数据库中查找登录的成员配置文件)。当我进行查询时,我可以 console.log 将查询返回的数据作为一个整体。如果我尝试访问数据成员,我会发现对象未定义。这是我查询的组件:

import React,  Component  from 'react';
import  Redirect  from 'react-router-dom'
import  graphql, compose  from 'react-apollo';
import  withFirebase  from '../Firebase';
import  getMemberByFBidQuery  from '../../queries/queries';

import DataList from '../wishes/MyDataList';

const INITIAL_STATE = 
    memberProfile: ,
    error: null


class DashboardGuts extends Component 
    constructor(props) 
        super(props);

        this.state =  ...INITIAL_STATE ;
    

    render() 
        const memberProfile = this.props.getMemberByFBidQuery.memberByFBid;
        console.log('memberProfile: ', memberProfile.id);

        return (
            <div className="dashboard container">
                <div className="row">
                    <div className="col s12 m6">
                        <h4>My Data List</h4>
                        <DataList memberProfile=memberProfile />
                    </div>
                </div>
            </div>
        )
    


const Dashboard = withFirebase(DashboardGuts)

export default compose(
    graphql(getMemberByFBidQuery, 
        name: "getMemberByFBidQuery",
        options: (props) => 
            return 
                variables: 
                    fbid: props.firebase.auth.O
                
            
        
    ),
)(Dashboard)

当我在上面的代码中控制台记录 memberProfile 时,我得到了我期望从查询返回的所有数据。 console.log 输出如下所示:

memberProfile:  
    firstname: "jo", lastname: "blo", id: "1234", 
     fbid: "5678", __typename: "Member"
     fbid: "5678"
     firstname: "jo"
     id: "1234"
     lastname: "smith"
     __typename: "Member"
     __proto__: Object
 

问题是当我尝试访问 memberProfile 对象中的任何字段时——比如 id,我得到了错误。例如,如果我更改此行:

console.log('memberProfile: ', memberProfile);

到这里:

console.log('memberProfile: ', memberProfile.id);

然后我收到无法访问未定义对象的 id 的错误。

关于如何访问该 id 属性的任何想法?如果有帮助,这里是实际的 graphQL 查询:

const getMemberByFBidQuery = gql`
query($fbid: String)
    memberByFBid(fbid: $fbid) 
        firstname,
        lastname,
        id,
        fbid
    

`

这是该查询的架构:

memberByFBid: 
        type: MemberType,
        args:  fbid:  type: GraphQLString  ,
        resolve(parent, args) 
            return Member.findOne( fbid: args.fbid );
        
    ,

这是 MemberType 的架构:

const MemberType = new GraphQLObjectType(
name: "Member",
fields: () => (
    id:  type: GraphQLID ,
    firstname:  type: GraphQLString ,
    lastname:  type: GraphQLString ,
    email:  type: GraphQLString ,
    fbid:  type: GraphQLString ,
    wishes: 
        type: GraphQLList(WishType),
        resolve(parent, args) 
            return Wish.find( memberId: parent.id )
        
    ,
    groups: 
        type: GraphQLList(MemberToGroupMapType),
        resolve(parent, args) 
            return MemberToGroupMap.find( memberId: parent.id );
        
    
)
);

提前感谢您的帮助!

根据 TLadd 的建议,我更改了渲染功能,但仍然出现错误。她现在是:

render() 
    console.log('look for loading: ', this.props);
    const  memberByFBid, loading, error  = this.props.getMemberByFBidQuery;

    if (loading) 
        return (<p>Loading...</p>);
     else if (error) 
        return (<p>Error!</p>);
    

    console.log('memberProfilexx: ', memberByFBid);

    return (
        <div className="dashboard container">
            <div className="row">
                <div className="col s12 m6">
                    <h4>My Wish List</h4>
                    <WishList memberProfile=memberByFBid />
                </div>
                <div className="col s12 m5 offset-m1">
                    <div>Hello</div>
                </div>
            </div>
        </div>
    )

但如果我尝试 console.log memberByFBid.id 而不仅仅是 memberByFBid,我仍然会收到错误消息。

【问题讨论】:

【参考方案1】:

您遇到此错误是因为当您的 DashboardGuts 组件首次尝试呈现时,您的查询尚未加载。来自数据属性上的react-apollo docs(在本例中为 getMemberByFBidQuery,因为您在 graphql HOC 中指定了自定义名称配置选项):

确保在渲染之前始终检查组件中的 data.loading 和 data.error。当您的组件执行其初始提取时,可能未定义包含您应用数据的 data.todos 等属性。检查 data.loading 和 data.error 有助于避免未定义数据的任何问题。

按照这个建议,你的渲染方法变成了类似

render() 
  const  memberByFBid, loading, error  = this.props.getMemberByFBidQuery;

  if (loading) 
    return <p>Loading...</p>;
   else if (error) 
    return <p>Error!</p>;
  

  console.log('memberProfile: ', memberProfile.id);
  return (
    <div className="dashboard container">
      <div className="row">
        <div className="col s12 m6">
          <h4>My Data List</h4>
          <DataList memberProfile=memberProfile />
        </div>
      </div>
    </div>
  )

您可能希望以更吸引人的方式处理加载/错误状态,但主要思想是您需要在渲染方法中考虑尚未加载的数据,因为它不会处于初始状态渲染。

【讨论】:

添加了您的建议 - 但仍然出现错误。通过检查是否加载或错误将渲染更改为您的建议。如果我尝试访问 ifs 下方的 memberByFBid.id,仍然会出现未定义的错误 我更新了我上面的帖子,包括根据您的建议更改我的渲染功能@TLadd 好的 - 意识到我无法在该组件中通过控制台将其注销,但我现在可以在将其传递到的组件中获取它。所以这很好!谢谢!

以上是关于访问查询返回对象的 id 字段将其更改为未定义的主要内容,如果未能解决你的问题,请参考以下文章

IQueryable 或 IList

当我使用点表示法时,字段返回未定义

Laravel 迁移 - 如何将 `id` 字段更改为主要字段并稍后自动递增

将访问查询转换为 sql 2012

为啥在尝试读取记录集字段时未定义访问 vba 抛出子或函数?

在 C++ 中,主函数是编程的入口点,我如何将其更改为其他函数?