Jak zbudować aplikację React za pomocą RTK-QUERY

Mar 08 2023
Przewodnik dla początkujących dotyczący pisania zapytań za pomocą rtk-query
Niemożliwe jest być Front-end developerem pracującym z Reactem i nie słyszeć o redux w swoim życiu. Większość firm używa redux w swojej bazie kodu, a znajomość podstawowych koncepcji stała się jedną z istot bycia Frontenderem.
Zdjęcie Fahima Muntashira na Unsplash

Niemożliwe jest być Front-end developerem pracującym z Reactem i nie słyszeć o redux w swoim życiu. Większość firm używa redux w swojej bazie kodu, a znajomość podstawowych koncepcji stała się jedną z istot bycia Frontenderem. Istnieje wiele dyskusji na temat używania lub nie używania go w swoim produkcie. Prawda jest taka, że ​​nigdy nie można znaleźć idealnego narzędzia do wszystkich projektów. Powinieneś zdecydować, które narzędzia najlepiej pasują do Twoich celów i produktu. Chociaż istnieją pewne zalety i wady każdego narzędzia, najważniejszą rzeczą jest kompromis między zaletami i wadami narzędzia dla CIEBIE .

RTK Query to potężne narzędzie do pobierania i buforowania danych. Został zaprojektowany w celu uproszczenia typowych przypadków ładowania danych w aplikacji internetowej, eliminując potrzebę samodzielnego pisania logiki pobierania i buforowania danych.

Jeśli używasz redux, zwłaszcza redux-toolkit , już wiesz, że rtk-query jest z nim wbudowaną zależnością. Istnieje wiele podobnych narzędzi, takich jak react-query, ale kiedy używasz redux-toolkit i masz już rtk-query w swoim pakiecie, dlaczego go nie użyć? Niektóre zalety trk-query to:

  • Jest w pełni kompatybilny z redux
  • Napisany w TypeScript
  • Ulepsza warstwę usług, aby była bardziej użyteczna i przenosi Twój projekt z automatycznie generowanymi haczykami na wyższy poziom
  • Można go śledzić i obserwować za pomocą redux-devtools
  • Ma naprawdę ładne zachowanie buforowania

Warunek wstępny

  1. Powinieneś znać Reacta
  2. Powinieneś znać koncepcje redux i redux-toolkit i chcieć ich używać w swoim projekcie
  3. Doświadczenie z TypeScriptem jest plusem, ale możesz po prostu usunąć części TS z kodów i działa z JavaScriptem dla Ciebie :)

Jak to działa?

Jak wspomniałem wcześniej, rtk-query to narzędzie do pobierania, które zapewnia mnóstwo funkcji, dzięki którym Twój projekt jest bardziej przejrzysty i nadaje się do ponownego użycia. Twoje usługi mogą być tworzone w kształcie punktów końcowych i zapytań za pomocą createApi , które jest całkowicie podobne do createReducer . Generuje haczyki dla twoich zapytań i możesz ich łatwo używać w swoich komponentach. Nie będziesz już potrzebować stanów ładowania, obsługi błędów, funkcji ponownego pobierania, pobierania wstępnego za pomocą useEffect i parserów danych, ponieważ rtk-query zajmie się tym za Ciebie.

W rzeczywistości zapytania to najmniejsze elementy twoich usług, które mogą być GET lub POST w celu pobrania lub wysłania danych na serwer. Wszystkie zapytania związane z jednostką są spakowane w jednym punkcie końcowym, który jest tworzony przez createApi . W końcu warstwa usług jest kombinacją różnych punktów końcowych, w tym ich własnych zapytań.

rtk-query używa interfejsu API pobierania z JavaScript. Ale możesz skonfigurować go tak, aby używał axios lub graphql. Ponadto zawija twoje zapytania przez zanurzenie , więc mutacja danych nie jest już problemem.

Graf warstwy usług i komponentów

Budowanie fundamentów

Możesz wybrać DOWOLNE narzędzia i konfigurację, które lubisz dla tego projektu. Użyję Vite, ale nie ma znaczenia, czy bardziej lubisz CRA, czy wolisz skonfigurować własną płytę kotłową. Po utworzeniu naszego projektu React powinniśmy zainstalować redux-toolkit + axios i skonfigurować go:

npm install @reduxjs/toolkit react-redux axios

// src/services/api.ts

const axiosBaseQuery =
  (): BaseQueryFn<AxiosRequestConfig, unknown, AxiosError> =>
  async ({ url, method, data, params }) => {
    try {
      Axios.defaults.baseURL = "https://jsonplaceholder.typicode.com/";
      const result = await Axios({
        url,
        method,
        data,
        params,
      });
      return { data: result.data };
    } catch (axiosError) {
      const error = axiosError as AxiosError;
      return {
        error,
      };
    }
  };

W tym projekcie wykorzystamy darmowe API JSONPlaceholder .

Po drugie, powinniśmy powiedzieć rtk-query, aby używał naszej niestandardowej funkcji zapytania zamiast JS fetch API. Jest to po prostu wykonalne, przekazując naszą funkcję do createApi .

// src/services/api.ts

export const apiService = createApi({
  baseQuery: axiosBaseQuery(),
  endpoints: () => ({}),
});

Na koniec musimy dodać apiService do sklepu redux i dodać sklep do naszej aplikacji:

// src/store/store.ts

export const store = configureStore({
  reducer: {
    [apiService.reducerPath]: apiService.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(apiService.middleware),
});
// src/main.tsx 

<Provider store={store}>
    <App />
 </Provider>

Tworzymy naszą pierwszą usługę

Zaczynamy od punktu końcowego GET , aby pobrać listę postów z serwera. Możemy po prostu użyć injectEndpoint API z rtk-query, aby utworzyć nasze punkty końcowe i dodać je do naszej podstawowej warstwy usług.

// src/services/posts.ts

// Interface of JSONPlaceholder posts
export interface Post {
  id: number;
  userId: number;
  title: string;
  body: string;
}

export const postService = apiService.injectEndpoints({
  endpoints: (build) => ({
    // query<ResultType, QueryArg>
    getPosts: build.query<Post[], null>({
      query: () => ({ method: "GET", url: "posts" }),
    }),
  }),
});

// Auto-generated hooks
export const { useGetPostsQuery } = postService;

Następnie rtk-query tworzy haczyki, abyś mógł łatwo pobrać te zapytania. Możesz przekazać więcej ustawień do swoich konstruktorów zapytań, takich jak transformResponse , których nie omawiamy, ponieważ wykraczają poza zakres tego artykułu.

Skorzystajmy z naszej pierwszej usługi

Teraz pora skorzystać z naszej usługi. rtk-query wygenerował dla nas hak useGetPostsQuery . Ten hak zwraca obiekt składający się z kilku użytecznych wartości do użycia. Podobnie jak stan ładowania, błąd, zwrócone dane i funkcja ponownego pobierania.

  • Stan ładowania: będzie prawdziwy , gdy wykonamy to zapytanie w naszym komponencie.
  • Obiekt błędu: Jeśli nasze zapytanie nie powiedzie się, zostanie zwrócony obiekt błędu, w przeciwnym razie jest to null .
  • dane: Nasze zwrócone dane. Jest pusty , dopóki nasze zapytanie nie zostanie pomyślnie wykonane .
  • funkcja ponownego pobierania: możemy użyć tej funkcji, aby ponownie uruchomić zapytanie, kiedy tylko zajdzie taka potrzeba. Na przykład na wypadek, gdybyśmy chcieli mieć przycisk „Spróbuj ponownie” lub przycisk odświeżania.
  • // src/components/PostList.tsx
    
    const PostList: React.FC<unknown> = () => {
      const { data: posts, isLoading, error, refetch } = useGetPostsQuery(null);
    
      if (isLoading) {
        return <div>Loading posts...</div>;
      }
    
      if (error) {
        return <ErrorBanner error={error as AxiosError} refetch={refetch} />;
      }
    
      return (
        <div>
          <h2>Posts</h2>
          <div>
            {posts?.map((post) => (
              <div className="postItem">
                <h4>{post.title}</h4>
                <p>{post.body}</p>
              </div>
            ))}
          </div>
        </div>
      );
    };
    
    export default PostList;
    

    Lista postów

Aby przejść dalej, omówimy również jedno zapytanie o mutację. Chcemy utworzyć post za pomocą formularza, który pobiera tytuł i treść od użytkowników. Zacznijmy od samego zapytania:

// src/services/posts.ts

export interface CreatePostDto {
  title: string;
  body: string;
}

export const postService = apiService.injectEndpoints({
  endpoints: (build) => ({
    // query<ResultType, QueryArg>
    getPosts: build.query<Post[], null>({
      query: () => ({ method: "GET", url: "posts" }),
    }),
    // We use mutation for POST endpoints
    createPost: build.mutation<Post, CreatePostDto>({
      query: (data) => ({
        method: "POST",
        url: "posts",
        // We pass static userId to simplify this part
        data: { userId: 1, ...data },
      }),
    }),
  }),
});

// Auto-generated hooks
export const { useGetPostsQuery, useCreatePostMutation } = postService;

  1. Ponieważ chcemy dodać trochę danych metodą POST , używamy build.mutation zamiast build.query .
  2. Określiliśmy nowy interfejs dla argumentów naszego punktu końcowego i przekazaliśmy odpowiednie dane do naszego żądania axios.

// src/components/PostForm.tsx

const PostForm: React.FC<unknown> = () => {
  const [title, setTitle] = useState<string>("");
  const [body, setBody] = useState<string>("");

  const [createPost, { isLoading }] = useCreatePostMutation();

  const submitForm = async (e: FormEvent) => {
    e.preventDefault();
    try {
      await createPost({ title, body });
    } catch (e) {
      console.log(e);
    }
  };

  return (
    <form onSubmit={submitForm}>
      <input
        name="title"
        type="text"
        placeholder="Title"
        value={title}
        onChange={(e) => setTitle(e.currentTarget.value)}
      />
      <textarea
        name="body"
        placeholder="Body..."
        rows={5}
        value={body}
        onChange={(e) => setBody(e.currentTarget.value)}
      />
      <input
        type="submit"
        value={isLoading ? "Wait..." : "Submit"}
        disabled={isLoading}
      />
    </form>
  );
};

export default PostForm;

Zawiń to

Omówiliśmy najważniejsze podstawowe koncepcje zapytania rtk. Zobaczyliśmy, jak możemy tworzyć nasze usługi i punkty końcowe w sposób modułowy oraz jak wykorzystywać fantastyczne automatycznie generowane hooki w naszych komponentach. Później opublikuję kolejne artykuły wyjaśniające bardziej zaawansowane funkcje i koncepcje zapytań rtk, takie jak buforowanie , pobieranie konfiguracji , przekształcanie danych itp.

Pełna baza kodu wszystkiego, co omówiliśmy, jest opublikowana w tym repozytorium i wdrożona na tej stronie .

Jeśli masz jakieś rekomendacje lub sugestie, nie wahaj się zapytać mnie przez moją prywatną pocztę lub dodać komentarz, a jeśli podobał Ci się ten artykuł, nie zapomnij o klaskaniu!

Więcej treści na PlainEnglish.io .

Zapisz się do naszego bezpłatnego cotygodniowego biuletynu . Śledź nas na Twitterze , LinkedIn , YouTube i Discordzie .

Zainteresowany skalowaniem startupu oprogramowania ? Sprawdź obwód .