skip to Main Content

Help me, I can’t figure out how to call functions in components, passing them as parameters. For example, to receive a full tour or removal. So that it is updated on the backend and in the store.
this is my API:

import { TourType } from "../../types/types";
import { api } from "./api";

export const tourAPI = api.injectEndpoints({
  endpoints: (builder) => ({
    getAllTour: builder.query<{ message: string; data: TourType[] }, void>({
      query: () => ({
        url: "/tour",
        method: "GET",
      }),
    }),
    getTourByTourNumber: builder.query<TourType, string>({
      query: (number) => ({
        url: `/tour/number/${number}`,
        method: "GET",
      }),
    }),
    editTour: builder.mutation<string, TourType>({
      query: (tour) => ({
        url: `/tour`,
        method: "PUT",
        body: tour,
      }),
    }),
    removeTour: builder.mutation<string, number>({
      query: (number) => ({
        url: `/tour`,
        method: "DELETE",
        body: { number: number },
      }),
    }),
    addTour: builder.mutation<TourType, TourType>({
      query: (tour) => ({
        url: "/tour/create",
        method: "POST",
        body: tour,
      }),
    }),
  }),
});

export const {
  useGetAllTourQuery,
  useGetTourByTourNumberQuery,
  useEditTourMutation,
  useRemoveTourMutation,
  useAddTourMutation,
} = tourAPI;

export const {
  endpoints: { getAllTour, getTourByTourNumber, editTour, removeTour, addTour },
} = tourAPI;

And my slicer:

import { createSlice } from "@reduxjs/toolkit";
import { TourType } from "../../types/types";
import { tourAPI } from "../api/tourAPI";
import { RootState } from "../../store/store";

interface InitialState {
  tour: TourType[];
  loading: boolean;
}

const initialState: InitialState = {
  tour: [],
  loading: true,
};

const slice = createSlice({
  name: "tour",
  initialState,
  reducers: {
    logout: () => initialState,
  },
  extraReducers: (builder) => {
    builder.addMatcher(
      tourAPI.endpoints.getAllTour.matchFulfilled,
      (state, action) => {
        state.tour = action.payload.data;
      }
    );
  },
});

export default slice.reducer;

export const selectTour = (state: RootState): TourType[] => state.tour.tour;

Now I get all the tours this way:

 const { data, isLoading } = useGetAllTourQuery();

I add it like this:

 const [addTour] = useAddTourMutation();
    ... 

    const handleAddTour = async (data: TourType) => {
    try {
    await addTour(data).unwrap();

        } catch (err) {
          const maybeError = isErrorWithMessage(err);
    
          if (maybeError) {
            setError(err.data.message);
          } else {
            setError("Error");
          }
        }

    };

the tour is added but the store is not updated and a new one does not appear on the page. Tell me which way to go?

2

Answers


  1. It doesn’t seem that you have done something to update the store.

    You have added the extra reducer to your state, which updates the state on successful result of getAllTour query, but you haven’t added an extra reducer for addTour.

    You should make changes in your slice:

    const slice = createSlice({
      name: "tour",
      initialState,
      reducers: {
        logout: () => initialState,
      },
      extraReducers: (builder) => {
        builder.addMatcher(
          tourAPI.endpoints.getAllTour.matchFulfilled,
          (state, action) => {
             state.tour = action.payload.data;
          }
        );
        builder.addMatcher(
          tourAPI.endpoints.addTour.matchFulfilled,
          (state, action) => {
            state.tour.push(action.payload.data);
          }
        );
      },
    });
    
    Login or Signup to reply.
  2. You can use cache tags to provide & invalidate cache results. Queries provide tags and mutations invalidate them to trigger subscribed queries to refetch automatically.

    See Automated Re-fetching, and specifically Invalidating Cache Data

    Example:

    export const tourAPI = api
      .enhanceEndpoints({
        // Only need this enhancement if tags not specified in `createApi`
        addTagTypes: ["tours", "tour"],
      })
      .injectEndpoints({
        endpoints: (builder) => ({
          getAllTour: builder.query<{ message: string; data: TourType[] }, void>({
            query: () => ({
              url: "/tour",
              method: "GET",
            }),
            providesTags: ["tours"], // <-- query provides tags
          }),
          getTourByTourNumber: builder.query<TourType, string>({
            query: (number) => ({
              url: `/tour/number/${number}`,
              method: "GET",
            }),
            providesTags: (result, error, tourNumber) => [
              { type: "tour", id: tourNumber }
            ],
          }),
          editTour: builder.mutation<string, TourType>({
            query: (tour) => ({
              url: `/tour`,
              method: "PUT",
              body: tour,
            }),
            invalidatesTags: (result, error, tourNumber) => [
              "tours",
              { type: "tour", id: tourNumber }
            ],
          }),
          removeTour: builder.mutation<string, number>({
            query: (number) => ({
              url: `/tour`,
              method: "DELETE",
              body: { number: number },
            }),
            invalidatesTags: (result, error, tourNumber) => [
              "tours",
              { type: "tour", id: tourNumber }
            ],
          }),
          addTour: builder.mutation<TourType, TourType>({
            query: (tour) => ({
              url: "/tour/create",
              method: "POST",
              body: tour,
            }),
            invalidatesTags: ["tours"], // <-- invalidates query tags
          }),
        }),
      });
    

    When the addTour trigger from the useAddTourMutation hook runs successfully, it will invalidate the "tours" cache tag. The getAllTour query endpoint that provides the "tours" tag will automatically refetch its data and trigger subscribed components running the useGetAllTourQuery to rerender with the updated query results.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search