useQuery() refetch isn't re-rendering component on items change

Hi there, I am running into an issue where I am noticing that my component isn’t re-rendering my items. I’m not an expert on React Hooks either so maybe I’m doing something wrong with my query:

const QUERY_SCHOOLS = gql`
  query SearchSchoolsQuery($query: String!) {
    schoolsSearch(query: $query) {
      id
      name
      domains
      stateProvince
      country
    }
  }
`

const SchoolsSearchAutoCompleteInput = () => {
  const {
    data: schoolResults,
    loading,
    error,
    refetch,
  } = useQuery(QUERY_SCHOOLS, {
    variables: { query: '' },
  })

  const [isLoading, setIsLoading] = useState(false)

  type SubjectHooks = [
    subject: Subject<string>,
    setSubject: Dispatch<SetStateAction<Subject<string>>>
  ]

  const [subject, setSubject]: SubjectHooks = useState(null)

  useEffect(() => {
    setIsLoading(() => loading)
  }, [loading])

  useEffect(() => {
    if (subject == null) {
      const sub = new BehaviorSubject('')

      setSubject(sub)
    } else {
      subject.pipe(debounceTime(500)).subscribe(async (query) => {
        refetch({ query })
      })
    }
  }, [subject])
  return (
    <>
      <FormControl py={5} variant="floating" id="schoolItems">
        <InputGroup>
          <AutoComplete openOnFocus onChange={(value, item) => {}}>
            <AutoCompleteInput
              variant="filled"
              placeholder={'What school do you go to?'}
              onChange={(event) => {
                if (subject) {
                  return subject.next(event.target.value)
                }
              }}
            />
            <SchoolsListingAutoCompleteList
              isLoading={isLoading}
              error={error}
              schoolsList={schoolResults?.schoolsSearch || []}
            />
          </AutoComplete>
        </InputGroup>
      </FormControl>
    </>
  )
}

const SchoolsListingAutoCompleteList = ({
  isLoading,
  error,
  schoolsList,
}: {
  isLoading: boolean
  error: any
  schoolsList?: School[]
}) => {
  if (isLoading) {
    return (
      <AutoCompleteList>
        <AutoCompleteItem
          key={'loading'}
          value={'Loading Schools...'}
          disabled
        />
        )
      </AutoCompleteList>
    )
  }
  if (error) {
    return (
      <AutoCompleteList>
        <AutoCompleteItem
          key={'error'}
          value={'Error fetching schools...'}
          disabled
        />
        )
      </AutoCompleteList>
    )
  }
  return (
    <AutoCompleteList>
      {schoolsList.map((school) => {
        return (
          <AutoCompleteItem
            key={school.id}
            value={school}
            getValue={(school) => school.name}
          />
        )
      })}
    </AutoCompleteList>
  )
}

In the above code, when I do call refetch(), I do notice that my logs do show that new items are fetched based on my input. However, after the input, it doesn’t seem to update my components at all with the list list of items that was fetched. I’d love to get some support on why this is happening. I think it has to do with the useQuery() hooks. However, I’d love to get a better understanding on why this is happening.

1 Like

@dom Was wondering if you can help provide some support on this! For some reason, refetch() isn’t forcing a component re-render.

Not really sure what subject is here but this seems overly complex

I think you want to useLazyQuery instead of useQuery

const [querySchools, { loading, data }] = useLazyQuery(QUERY_SCHOOLS)

you can then debounce the querySchools function onChange

i have same problem