React Query: InvalidateQuery not working to update users list

8.3k Views Asked by At

I have a simple app that has a form and list. Currently, I am using query client.InvalidateQueries to update the users' list after submitting the form. As the documentation says, using InvalidateQuery will trigger refetching, but somehow I had not seen an update to the list after adding users. Am I missing something?

Add User

import React, { useState } from 'react';
import { useFormik } from 'formik';
import Input from '../../elements/Input/Input';
import * as Yup from 'yup';
import { QueryClient, useMutation } from 'react-query';
import axios from 'axios';

const queryClient = new QueryClient();

const CreateItemView = () => {
  function gen4() {
    return Math.random().toString(16).slice(-4);
  }

  function generateID(prefix) {
    return (prefix || '').concat([gen4(), gen4(), gen4(), gen4(), gen4(), gen4(), gen4(), gen4()].join(''));
  }

  const mutation = useMutation(
    (formData) => {
      axios.post('http://localhost:8000/users', formData).then((response) => console.log(response));
    },
    {
      onSuccess: () => {
        queryClient.invalidateQueries('users');
      },
    },
  );

  const [data, setData] = useState([]);
  const initialValues = {
    id: '',
    name: '',
    email: '',
    channel: '',
  };
  const onSubmit = (values, { resetForm }) => {
    setData([...data, values]);
    const ID = generateID().toString();
    values.id = ID;
    mutation.mutate(values);
    resetForm();
  };
  const validationSchema = Yup.object({
    name: Yup.string().required('Required!'),
    email: Yup.string().email('Invalid format').required('Required!'),
    channel: Yup.string().required('Required!'),
  });
  const formik = useFormik({
    initialValues,
    onSubmit,
    validationSchema,
  });

  return (
    <div>
      <form onSubmit={formik.handleSubmit}>
        <Input type={'text'} name={'name'} id={'name'} label={'Name'} formik={formik} />
        <Input type={'email'} name={'email'} id={'email'} label={'Email'} formik={formik} />
        <Input type={'text'} name={'channel'} id={'channel'} label={'channel'} formik={formik} />
        <button type="submit">Submit</button>
      </form>
    </div>
  );
};

export default CreateItemView;

User's list

import React from 'react';
import ListView from './ListView';
import { useQuery } from 'react-query';
import axios from 'axios';

const getUsers = async () => {
  const response = await axios.get('http://localhost:8000/users');
  return response.data;
};
const ListContainer = () => {
  const { data, isLoading, isFetching } = useQuery('users', getUsers);
  console.log('list', data);
  return <div>{isFetching ? 'loading...' : <ListView dataSource={data} />}</div>;
};

export default ListContainer;
3

There are 3 best solutions below

0
Tarik Gadoumi On

i think the solution for your problem is to replace this :

 onSuccess: () => {
        queryClient.invalidateQueries('users');
      },

By this :

onSettled:() => {
            queryClient.invalidateQueries('users');
          },
0
Tomas Vancoillie On

You have to return the fetch function in the mutation. The onSuccess handler will fire when the promise is resolved.

const mutation = useMutation(
    formData => {
      return axios.post('http://localhost:8000/users', formData)
               .then((response) => console.log(response));
    },
    {
      onSuccess: () => {
        queryClient.invalidateQueries('users');
      },
    },
  );
0
Chisom Maxwell On

you should use the same instance of queryClient from the root of your app which is accessible via the useQueryClient() hook. Hence you should be doing const queryClient = useQueryClient() instead of generating new instance with const queryClient = new QueryClient().