Search code examples
graphqlrelayjsgraphcoolrelaymodern

Relay Modern node does not contain fragment properties


I have the following setup in my React Project:

export default class OverviewScreen extends React.Component<any, any> {

public render() {

    return (
        <QueryRenderer
            environment={environment}
            query={OverviewScreenQuery}
            render={this.queryRender}/>
    );
}

protected queryRender({error, props}): JSX.Element {

    if (error) {
        return <div>{error.message}</div>;
    } else if (props) {
        return (
            <div>
                <div>
                    <ActivityOfferList viewer={props.viewer} title="Titel"/>
                    <ActivityTypeListsFragment viewer={props.viewer}/>
                </div>
            </div>
        );
    }
    return <div>Loading...</div>;
}
}

const OverviewScreenQuery = graphql`
query OverviewScreenQuery {
    viewer {
        ...HorizontalOfferList_viewer
        ...ActivityTypeLists_viewer
    }
}`;

class ActivityTypeLists extends React.Component<IHorizontalOfferListProps, any> {

public render() {

    return (
        <div>
        {this.props.viewer.allActivityTypes.edges.map((typeEdge) => {
            let typeNode = typeEdge.node;
            return this.getCardListForActivityType(typeNode);
        })}
        </div>
    );
}

private getCardListForActivityType(typeNode: any) {
    console.log(typeNode);

    return (
        <CardList key={typeNode.__id} title={typeNode.title}>
            {typeNode.activities.edges.map(({node}) => {
                return (
                    <RelayPicturedTypeActivityCard key={node.__id} offer={node} activityType={typeNode}/>
                );
            })}
        </CardList>
    );
}
}

export const ActivityTypeListsFragment = createFragmentContainer(ActivityTypeLists, graphql`
fragment ActivityTypeLists_viewer on Viewer {
    allActivityTypes(first: 5) {
        edges {
            node {
                ...PicturedTypeActivityCard_offer
            }
        }
    }
}
`);

export class PicturedTypeActivityCard extends React.Component<any, any> {

    public render() {
        return (
            <PicturedCard title={this.props.offer.title} subtitle={this.props.activityType.title} width={3}/>
        );
    }
}

export const RelayPicturedTypeActivityCard = createFragmentContainer(PicturedTypeActivityCard, graphql`
    fragment PicturedTypeActivityCard_offer on ActivityType {
        title
        activities(first: 4) {
            edges {
            node {
                id
                title
            }
        }
    }
    }
`);

Which should work and give me the correct result from the graphcool relay endpoint.

The Network call to the relay endpoint is indeed correct and I receive all the ActivityTypes and their activities and titles from my endpoint.

But somehow in the function getCardListForActivityType() the typeNode only contains the __id of the node as data and no title at all:

enter image description here

If I insert title and activities directly instead of using

...PicturedTypeActivityCard_offer

then the data also gets passed down correctly. So something with the Fragment must be off.


Why is it that the network call is complete and uses the fragment correctly to fetch the data, but the node object never gets the fetched data?


Solution

  • This is indeed correct behavior.

    Your components must, individually, specify all their own data dependencies, Relay will only pass to the component the data it asked for. Since your component is not asking any data, it's receiving an empty object.

    That __id you see is used internally by Relay and you should not rely on it (that is why it has the __ prefix).

    Basically, the prop viewer on ActivityTypeLists component will have exactly the same format than the query requested on the ActivityTypeLists_viewer fragment, without any other fragments from other components that you are referencing there.

    This is known as data masking, see more in the following links:

    https://facebook.github.io/relay/docs/en/thinking-in-relay.html#data-masking https://facebook.github.io/relay/docs/en/graphql-in-relay.html#relaymask-boolean