How data.refetch() function from react-apollo works

15,271

Solution 1

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);

Solution 2

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

Share:
15,271
SaidAkh
Author by

SaidAkh

Updated on June 29, 2022

Comments

  • SaidAkh
    SaidAkh almost 2 years

    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