I'm having some issues setting up a refetchContainer in Relay Modern. A parent component is the QueryRenderer, which runs an initial query, populating the child component's props appropriately (a-prop-riately? eh? eh?!) . The refetchContainer specifies all our variables, and on an input field's onChange event, re-runs a query with the new variables. This all works perfectly, except that the child's props are never updated with the new data received. I can drill down the Relay store and see that the query was indeed received with the appropriate data. Been bangin' my head against this for a while and I would appreciate some help. Probably something simple I'm missing. And Lord knows Relay Modern documentation is sparse.
I've poked around and can't find an appropriate solution. This guy seems to be having a similar issue: relay refetch doesn't show the result
The parent component with QueryRenderer:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { graphql, QueryRenderer } from 'react-relay';
import Search from './Search';
const propTypes = {
auth: PropTypes.object.isRequired,
};
class SearchContainer extends Component {
render() {
return (
<QueryRenderer
query={graphql`
query SearchContainerQuery($search: String!){
users: searchUsers(search:$search, first:10){
...Search_users
}
}`}
variables={{ search: 'someDefaultSearch' }}
environment={this.props.auth.environment}
render={({ error, props }) => {
if (error) {
console.log(error);
}
if (props) {
return <Search users={props.users} />;
}
return <div>No Dice</div>;
}}
/>
);
}
}
SearchContainer.propTypes = propTypes;
export default connect(state => ({ auth: state.auth }))(SearchContainer);
The child component with createRefetchContainer:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { createRefetchContainer, graphql } from 'react-relay';
const propTypes = {
relay: PropTypes.object.isRequired,
users: PropTypes.object,
};
const defaultProps = {
users: {},
};
class Search extends Component {
render() {
return (
<div>
<input
type="text"
onChange={(e) => {
e.preventDefault();
this.props.relay.refetch({
search: e.target.value,
});
}}
/>
<ul>
{this.props.users.nodes.map(user =>
<li key={user.id}>{user.username}</li>,
)}
</ul>
</div>
);
}
}
Search.propTypes = propTypes;
Search.defaultProps = defaultProps;
export default createRefetchContainer(
Search,
{
users: graphql.experimental`
fragment Search_users on SearchUsersConnection
@argumentDefinitions(
search: {type: "String", defaultValue: ""}
) {
nodes {
id
displayName
username
}
}
`,
},
graphql.experimental`
query SearchRefetchQuery($search: String!) {
users: searchUsers(search:$search, first:10){
...Search_users @arguments(search: $search)
}
}
`,
);
GraphQL looks like this:
# A connection to a list of `User` values.
type SearchUsersConnection {
# Information to aid in pagination.
pageInfo: PageInfo!
# The count of *all* `User` you could get from the connection.
totalCount: Int
# A list of edges which contains the `User` and cursor to aid in pagination.
edges: [SearchUsersEdge]
# A list of `User` objects.
nodes: [User]
}
Network calls are made appropriately, and data is returned as expected. NetworkCalls
It seems the @arguments directive can be left out of the refetch query here:
query SearchRefetchQuery($search: String!) {
users: searchUsers(search:$search, first:10){
...Search_users @arguments(search: $search)
}
}
(removing it seems to have no effect)
I've tried adding the @arguments directive to the parent component's fragment as per the recommendation here: Pass variables to fragment container in relay modern, to no effect.
fragment Search_user on RootQueryType
. My last suggestion is turning your debugger on and see whats going on when you get the data. – Gristede