1

I've been trying Apollo out with React and am currently facing a problem with it.

I have basic data where a Product belongs to many Categories

query getProduct{
    product(id: 1){
        id
        name
        categories{id,name}
    }
}

As expected this returns something like this

{
  "data": {
    "p": {
      "id": 1,
      "name": "Samsung Galaxy S7",
      "categories": [
        {
          "name": "Phone"
        },
        {
          "name": "Samsung"
        }
      ]
    }
  }
}

Here is my react Component

class TileProductComponent extends Component{

    constructor(...args){
        super(...args)
    }

    render(){
        if(this.props.data.loading)
            return <div>Loading...</div>

        var product = this.props.data.p

        console.log(this.props.data)

        return (
            <div> {product.name} </div>
        )
    }
}

var TileProduct = graphql(
    gql`
        query TestQuery($id: Int!){
            product(id: $id){
                id
                name
                categories{id,name}
            }
        }
    `,
    {
        options : {
            variables : {id:1}
        }
    }
)(TileProductComponent)

But once it is passed in the react component i found it to be (from the console.log(this.props.data))

    "product": {
      "id": 1,
      "name": "Phone",
      "categories": [
        {
          "name": "Phone"
        },
        {
          "name": "Samsung"
        }
      ]
    }

The product name adopts the name of the first category for some reason ? I'm guessing the id will too. A fix would be to change the name of fields in the schemas, but it shouldn't really do that anyway in my opinion.

Is this a known issue or am I the only one experiencing this? Any proposed solution ?

zbenhadi
  • 23
  • 1
  • 4
  • Do you have a `dataIdFromObject` defined? It sounds like perhaps your products and categories have overlapping IDs, which are causing Apollo to think they are the same object. Can you insert your Apollo Client initialization code? – stubailo Oct 13 '16 at 22:55
  • var netfworkInterface = createNetworkInterface('http://localhost:3030/graphql') this.client = new ApolloClient({ netfworkInterface, dataIdFromObject: r => r.id }) – zbenhadi Oct 13 '16 at 23:03
  • So i guess i have to return a different result for different "collections", for example i could do "product."+r.id for the products and so on, but how do i know which collection it came from, since i only have the document itself – zbenhadi Oct 14 '16 at 00:11
  • Try this: https://github.com/apollostack/GitHunt-React/blob/380bedaef97f2a0932c1ab33bd964812d4a8a65e/ui/client.js#L42-L48 – stubailo Oct 15 '16 at 03:39

1 Answers1

0

The problem is with your dataIdFromObject function. This function needs to return a unique value for different objects that come from the server. One easy way to do this is to use the __typename field built into GraphQL with your ID field. Here's a code snippet:

const client = new ApolloClient({
  queryTransformer: addTypename,
  dataIdFromObject: (result) => {
    if (result.id && result.__typename) {
      return result.__typename + result.id;
    }
    return null;
  }
});

To see it used in the context of an app, check out the GitHunt frontend example, which uses SQL incremental IDs: https://github.com/apollostack/GitHunt-React/blob/380bedaef97f2a0932c1ab33bd964812d4a8a65e/ui/client.js#L42-L48

stubailo
  • 6,077
  • 1
  • 26
  • 32