When writing a GraphQL query fragment as part of a RelayContainer
, I've been struggling with how to set query variables in certain situations. The basics outlined in the documentation are simple enough. But given the static nature of these queries and how a RelayContainer
is a higher-order React Component, I'm not sure the best way to handle this when the input needed for a query is an object from an external source such as a Redux store. I don't have any way to retrieve data from that store before the component loads, so as a workaround I've been using the @include
directive and setting a ready variable to true after the component loads:
class ListData extends React.Component {
// ... proptypes
componentWillMount() {
const { listDataInfo } = this.context.store.getState(); // Retrieve from Redux store
this.props.relay.setVariables({
input: {
id: listDataInfo.id,
user: listDataInfo.user
},
inputReady: true,
});
// The query will now execute and fetch all the data
}
render() {
return (
{/* view */}
)
}
}
export default Relay.createContainer(ListData, {
initialVariables: {
input: null,
inputReady: false,
},
fragments: {
listData: () => Relay.QL`
fragment on ListDataQuery {
listData(input: $input) @include(if: $inputReady) {
city
state
zip
phone
}
}
`,
},
});
In the end this works as expected, but I'm concerned that this is more of a hack, and that I'm missing something important with how Relay should be handling query variables. Is there a better way to do this? The prepareVariables looked like it could be useful but I still wouldn't have access to my data store. Here are my apparent options:
RelayNetworkLayer
(which has access to my store) to intercept my queries and set the variables from an external store there. This also feels like a hack.I found this gist that accomplishes exactly what I'm looking for. It lets you pass in redux state variables via @container
decorator with the property variablesFromState
. Essentially it will return either a standard Relay Container (if variablesFromState
is not set) or a Relay Container wrapped in a redux Provider
wrapper with the redux store instance passed in.