Delegating fragments to children with Relay

434 views Asked by At

I want to do something like this in a component:

Relay.createContainer(Component, {
  fragments: {
    thing: AnotherComponent.getFragment('thing')
  }
}

This would ideally set the fragment thing on my current component to use the fragment thing on one of it's child components. Effectively delegating the responsibility of knowing what thing is down to whatever uses it. Then the component that includes Component can call Component.getFragment('thing') which will call AnotherComponent.getFragment('thing').

Does anyone know how to do this?

UPDATE

The only way I've found to make this work is via syntax like

Relay.createContainer(Component, {
  fragments: {
    thing: Relay.QL`
      ${AnotherComponent.getFragment('thing')}
    `
  }
}

This hits the server correctly, and the server executes the query specified by AnotherComponent, but now the return value of the query is not provided in the props of Component

UPDATE 2

I've found that repeated nesting of this type produces a query like:

query Router {

  store {

    ...F3

  }

}
fragment F0 on Store {

  _fields2w4En2:fields(labels:["Country","Function"],owner_type:"requisitions") {

    choices {

      id,

      label

    },

    id
,

    label
  }

}
fragment F1 on Store {

  ...F0

}
fragment F2 on Store {

  ...F1

}
fragment F3 on Store {

  ...F2

}

Where at the base level I had a query like this:

export default Relay.createContainer(SearchBar, {
  fragments: {
    searchFields: () => Relay.QL`
      fragment searchFields on Store {
        searchFields: fields(labels: ["Country", "Function"], owner_type: "requisitions") {
          label
          choices {
            id
            label
          }
        }
      }
    `,
  },
});
1

There are 1 answers

3
monastic-panic On BEST ANSWER

So the reason the straight forward approach doesn't work is becasue getFragment doesn't actually return a fragment (ugh), but a reference to a fragment that is specific to the container that declares it. Luckily tho you can get the plain fragment from that, with: AnotherComponent.getFragment('thing').getFragment().

see this playground example for a demonstration