Relay: [Modern rc.3] fragment data is null when using createFragmentContainer

Created on 8 May 2017  路  17Comments  路  Source: facebook/relay

in my posts.js file I have the QueryRenderer that passes the props to the child postLists component.

     <QueryRenderer
           environment={environment}
             query={GetAllPosts}
            render={({error, props}) => {
              if(props) {
                console.log(props.viewer)
                return <PostList posts={props.viewer}/>
              }

             return <Text style={{marginTop:20}}>Loading...</Text>
         }
        }/>

this is the post_list.js

  class PostList extends Component {
    render () {
       return (
       <View>
          {this.renderPosts(this.props.posts)}
       </View>
     )
   }
   renderPosts(posts) {
     if(!posts) {
        return <Text>No Posts</Text>
      }
     return posts.edges.map(post=>{
     return <PostItem post={post.node}/>
    })
   }
}

  export default createFragmentContainer(
    PostList,
    graphql`
    fragment post_list_posts on postEdges {
      node {
        ...post_item_post
      }
    }
  `
)

and the post_item.js

  class PostItem extends React.Component {
    render() {
      const post = this.props.post;
       return (
         <View>
           <Text>{post.content}</Text>
        </View>
      )
  }
}

 export default createFragmentContainer(
    PostItem,
    graphql`
       fragment post_item_post on postNode {
       Id
       content
      }
   `
  )

and finally the query itself,

    export default graphql`
      query getPostsQuery {
      viewer {
         edges {
             ...post_list_posts
         }
     }
  }
 `

Now when I console.log (props.viewer) I get

      { edges: 
   [ { __fragments: { post_list_posts: {} },
       __id: 'client:root:viewer:edges:0' },
     { __fragments: { post_list_posts: {} },
       __id: 'client:root:viewer:edges:1' },
     { __fragments: { post_list_posts: {} },
       __id: 'client:root:viewer:edges:2' },
     { __fragments: { post_list_posts: {} },
       __id: 'client:root:viewer:edges:3' },
     { __fragments: { post_list_posts: {} },
       __id: 'client:root:viewer:edges:4' } ] }

Most helpful comment

@saudpunjwani101 the render function of QueryRenderer does not print data, it only prints the containers
In order to see the data that it fetched with Relay, you need to pass it down atleast one container to see the data.

PS: Make shure you pass it down correct, else you will not see any.

All 17 comments

could you inline your query on QueryRenderer and see if it works?

doesn't work already tried

please try this:

 if(props) {
                console.log(props.viewer) // don't console in this line
                return <PostList viewer={props.viewer}/> //change posts to viewer
              }

now your all posts is inside viewer.posts

 class PostList extends Component {
    render () {
       console.log(this.props.viewer.posts) // instead debug in this area
       return (
       <View>
          {this.renderPosts(this.props.viewer.posts)} //this line
       </View>
     )
   }

@saudpunjwani101 the render function of QueryRenderer does not print data, it only prints the containers
In order to see the data that it fetched with Relay, you need to pass it down atleast one container to see the data.

PS: Make shure you pass it down correct, else you will not see any.

Using postContainer component as suggested.

   class PostContainer extends Component {
     render() {
     console.log(this.props.viewer.posts)
     return (
       <PostList viewer={this.props.viewer}/>
     )
   }
 }

also changed from props posts to viewer. But same result.. this.props.viewer.posts get undefined. @nosykretts why does it have to be viewer instead of posts?

I guess this doesn't have anything to do with using react-native?

@saudpunjwani101 You can ignore my comment above. I dont watch closely your final query and as @stoffern suggested you need to pass down the correct props from container renderer to fragment container. Please go back to your original code and change this line:

if(props) {
  return <PostList posts={props.viewer.edges}/>
}

PS: Im not very good in english and still learning relay too.

Yes I used a container component before passing the props to postList component. But the data is null

I know this trivial to do in React native. Can you give us what final Request payload look like that sent to graphQL server and can you confirm the data is arriving? something look like this:
screen shot 2017-05-10 at 11 37 54 pm
screen shot 2017-05-10 at 11 38 03 pm

@saudpunjwani101 to be clear:

<QueryRenderer
  environment={environment}
  query={GetAllPosts}
  render={({error, props}) => {
    console.log(props.viewer) 
    //this will return null whatever if the code is correct or not.
    //props here only contain fragments and they are not parsed before they are on the correct component 
  }
/>

You will need to pass it correct down to the PostList component and print props here..
If you see null here, you pass them wrong or have a wrong setup in your fragments

I use it in React Native and it works just fine.

well u can see my code above. Can u tell me what I'm doing wrong? thx

start here:

class PostList extends Component {
  render () {
    console.log(this.props.posts) //should log [{id: id},....]
    return (
      {
        (this.props.posts.someVariable && this.props.posts.someVariable.edges.length > 0)?
        <Text>No Posts</Text>:
        <View>
          { posts.edges.map(post=> <View>{post.node.id}</View>) }
        </View>
      }
   )
  }
}
PostList = createFragmentContainer(
  PostList,
  graphql`
    fragment post_list_posts on Viewer {  //You need to change postEdges.. i dont know what the name is here..
      someVariable{  // make a name here.. both GrapqhQL and generate new Schema - you should not place a connection(viewer) on rootQuery
        edges {
          node {  //moved node to the main query
            id
          }
        }
    }
  `
)

export default props => (
  <QueryRenderer
    environment={environment}
    query={ graphql`
      query getPostsQuery {
        viewer {
          ...post_list_posts
        }
      }
    `}
    render={({error, props}) => {
      console.log(props.viewer) // should console log null.
      if(props) return <PostList posts={props.viewer}/>
      return <Text style={{marginTop:20}}>Loading...</Text>
    }
  />
)

and use spaces over tabs, this is why i cant copy paste your code 馃槈

@saudpunjwani101 status?

Closing this since @stoffern has a clear answer, thanks!

yup solved

@saudpunjwani101 how to solve? i have a same issue and i use createRefetchContainer.my fragment return arrays.

Could u give more details

Was this page helpful?
0 / 5 - 0 ratings