On the frontend, I am using ReactJS and trying to build-in a filtering option to a list view. The list view correctly getting data from graphql endpoint by issuing this graphql query:
query getVideos($filterByBook: ID, $limit: Int!, $after: ID) {
videosQuery(filterByBook: $filterByBook, limit: $limit, after: $after) {
totalCount
edges {
cursor
node {
id
title
ytDefaultThumbnail
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
On the initial load $filterByBook
variable is set to null
, so the query correctly returns all pages for all nodes (query returns a paginated result). Then, by clicking on the filter (filter by book) another graphql query is issuing, but it always returns the same data
. Here is a code snippet for filtering component
renderFilters() {
const { listOfBooksWithChapters, refetch } = this.props;
return (
<Row>
<FilterBooks
onBookTitleClickParam={(onBookTitleClickParam) => {
return refetch({
variables: {
limit: 3,
after: 0,
filterByBook: onBookTitleClickParam
}
})
}}
listOfBooksWithChapters={listOfBooksWithChapters}
/>
</Row>
)
}
And, here is complete code without imports for the list view component
class VideoList extends React.Component {
constructor(props) {
super(props);
this.subscription = null;
}
componentWillUnmount() {
if (this.subscription) {
// unsubscribe
this.subscription();
}
}
renderVideos() {
const { videosQuery } = this.props;
return videosQuery.edges.map(({ node: { id, title, ytDefaultThumbnail } }) => {
return (
<Col sm="4" key={id}>
<Card>
<CardImg top width="100%" src={ytDefaultThumbnail} alt="video image" />
<CardBlock>
<CardTitle>
<Link
className="post-link"
to={`/video/${id}`}>
{title}
</Link>
</CardTitle>
</CardBlock>
</Card>
</Col>
);
});
}
renderLoadMore() {
const { videosQuery, loadMoreRows } = this.props;
if (videosQuery.pageInfo.hasNextPage) {
return (
<Button id="load-more" color="primary" onClick={loadMoreRows}>
Load more ...
</Button>
);
}
}
renderFilters() {
const { listOfBooksWithChapters, refetch } = this.props;
return (
<Row>
<FilterBooks
onBookTitleClickParam={(onBookTitleClickParam) => {
return refetch({
variables: {
limit: 3,
after: 0,
filterByBook: onBookTitleClickParam
}
})
}}
listOfBooksWithChapters={listOfBooksWithChapters}
/>
</Row>
)
}
render() {
const { loading, videosQuery } = this.props;
if (loading && !videosQuery) {
return (
<div>{ /* loading... */}</div>
);
} else {
return (
<div>
<Helmet
title="Videos list"
meta={[{
name: 'description',
content: 'List of all videos'
}]} />
<h2>Videos</h2>
{this.renderFilters()}
<Row>
{this.renderVideos()}
</Row>
<div>
<small>({videosQuery.edges.length} / {videosQuery.totalCount})</small>
</div>
{this.renderLoadMore()}
</div>
);
}
}
}
export default compose(
graphql(VIDEOS_QUERY, {
options: () => {
return {
variables: {
limit: 3,
after: 0,
filterByBook: null
},
};
},
props: ({ data }) => {
const { loading, videosQuery, fetchMore, subscribeToMore, refetch } = data;
const loadMoreRows = () => {
return fetchMore({
variables: {
after: videosQuery.pageInfo.endCursor,
},
updateQuery: (previousResult, { fetchMoreResult }) => {
const totalCount = fetchMoreResult.videosQuery.totalCount;
const newEdges = fetchMoreResult.videosQuery.edges;
const pageInfo = fetchMoreResult.videosQuery.pageInfo;
return {
videosQuery: {
totalCount,
edges: [...previousResult.videosQuery.edges, ...newEdges],
pageInfo,
__typename: "VideosQuery"
}
};
}
});
};
return { loading, videosQuery, subscribeToMore, loadMoreRows, refetch };
}
}),
graphql(LIST_BOOKS_QUERY, {
props: ({ data }) => {
const { listOfBooksWithChapters } = data;
return { listOfBooksWithChapters };
}
}),
)(VideoList);
Question:
Why refetch
function returns data without taking into account new variable filterByBook
? How to check which variables
object I supplied to the refetch
function? Do I need to remap data that I receive from refetch
function back to the component props
?
EDIT:
I found the way to find what variable
object I supplied to the query and found that variable
object on filtering event returns this data
variables:Object
after:0
limit:3
variables:Object
after:0
filterByBook:"2"
limit:3
It seem that refetch
function is not meant to refetch data with different variables set (see this discussion).
I finally and successfully solved my issue with the help from this article
you can do it by adding refetch in useQuery
const {loading, data, error,refetch} = useQuery(GET_ALL_PROJECTS,
{
variables: {id: JSON.parse(localStorage.getItem("user")).id}
});
then call function refetch()
const saveChange = input => {
refetch();
};
OR
const saveChange = input => {
setIsOpen(false);
addProject({
variables: {
createBacklogInput: {
backlogTitle: backlogInput,
project:id
}
}
}).then(refetch);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With