reactjstypescriptreact-query

React Query Mutation and TypeScript error - Argument of type '{ surgeryID: any; stageTitle: any; }' is not assignable to parameter of type 'void'


I'm using react-query to fetch, and post data from my database on supabase. I created a hook for adding a record using react-query:

export function useCreateSurgeryStage() {
  const { mutate: createSurgeryStage, isLoading: isCreating } = useMutation({
    mutationFn: ({ surgeryID, stageTitle }) =>
      createSurgeryStageById(surgeryID, stageTitle),
    onSuccess: () => {
      console.log(
        // `sent surgery creation request with surgeryID: ${surgeryID} and stageTitle: ${stageTitle}`
        `sent surgery creation request...`
      );
    },
    onError: (err) => console.log("ERROR RECEIVED:", err.message),
  });

  return { isCreating, createSurgeryStage };
}

Here's the mutation function that it calls, which is what actually adds the records into the db:

interface SurgeryStage {
  surgeryID: number;
  stageTitle: string;
}
export async function createSurgeryStageById(
  surgeryID: number,
  stageTitle: string
): Promise<SurgeryStage> {
  if (!surgeryID || !stageTitle) {
    console.log(
      `createSurgeryStageById API: didn't correctly receive params: surgeryID:${surgeryID}, stageTitle:${stageTitle}`
    );
    return;
  }

  const { data: stage, error } = await supabase.from("Stages").insert([
    {
      surgeryID,
      stageTitle,
    },
  ]);

  if (error) throw error;

  return stage;
}

This all works exactly as expected: I can add a record into the database using the hook I made with react-query. But typescript gives me the warning message: Argument of type '{ surgeryID: any; stageTitle: any; }' is not assignable to parameter of type 'void'.

The warning message is when I try to pass an object into my createSurgeryStage function (which is an alias of the mutate function, from useMutation hook). The handler function:

function handleSurgeryStageInsertion({ stageTitle }) {
    const surgeryStage = { surgeryID: channelQuery, stageTitle };
    createSurgeryStage(surgeryStage, {
      onSettled: reset(),
    });
  }

Solution

  • You function is returning a value called stage. But in your function declaration you haven't specified what your function will return. If you don't specify the return type then the return type is considered as void by default. If you don't want to return the value stage from the function then you can remove the return type or else declare the return type like this:

    Some other changes:

    1. createSurgeryStageById returns Promise of SurgeryStage or null as you return if values are not given
    2. Explicitly return null
    3. Define stage for insert as supabase insert does not return data
    4. Throw new Error
    5. Define type of err in onError: (err: Error)
    
    interface SurgeryStage {
      surgeryID: number;
      stageTitle: string;
    }
    
    export async function createSurgeryStageById(
      surgeryID: number,
      stageTitle: string,
    ): Promise<SurgeryStage | null> { // Added null as return type
      if (!surgeryID || !stageTitle) {
        console.log(
          `createSurgeryStageById API: didn't correctly receive params: surgeryID:${surgeryID}, stageTitle:${stageTitle}`,
        );
        return null; // explicit null as return type
      }
    
      // declare stage separately
      const stage: SurgeryStage = {
        surgeryID,
        stageTitle,
      };
    
      const { error } = await supabase.from('Stages').insert([ // the insert query does not return data
        stage
      ]);
    
      if (error) throw new Error(error.message); // throw the error as new error
    
      return stage;
    }
    
    export function useCreateSurgeryStage() {
      const { mutate: createSurgeryStage, isLoading: isCreating } = useMutation({
        mutationFn: ({ surgeryID, stageTitle }: SurgeryStage) =>
          createSurgeryStageById(surgeryID, stageTitle),
        onSuccess: () => {
          console.log(
            // `sent surgery creation request with surgeryID: ${surgeryID} and stageTitle: ${stageTitle}`
            'sent surgery creation request...',
          );
        },
        onError: (err: Error) => console.log('ERROR RECEIVED:', err.message), // Define type of err
      });
    
      return { isCreating, createSurgeryStage };
    }
    

    Also your function is an async function. So we have to wrap SurgeryStage inside Promise.