Heim >Web-Frontend >js-Tutorial >Effiziente Datenverarbeitung in React Native mit RTK-Abfrage

Effiziente Datenverarbeitung in React Native mit RTK-Abfrage

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-11-30 10:01:14950Durchsuche

In diesem Leitfaden behandeln wir Folgendes:

  • CRUD-Operationen
  • Paginierung
  • Redux bleibt bei RTK-Abfrage bestehen
  • Verwendung mehrerer Basis-URLs
  • Geschützte und öffentliche Routen
  • Cache-Verwaltung und Invalidierung

Efficient Data Handling in React Native with RTK Query

RTK Query ist ein erweitertes Datenabruf- und Caching-Tool, das in Redux Toolkit (RTK) integriert ist. Es optimiert API-Interaktionen durch die Generierung von Redux-Slices und Hooks für häufige Aufgaben wie das Abrufen, Zwischenspeichern und Aktualisieren von Daten. Zu den Hauptmerkmalen gehören:

  1. Automatisches Caching: RTK Query speichert Daten im Cache und ruft sie automatisch erneut ab, wenn Daten ungültig werden, um sicherzustellen, dass die Benutzeroberfläche immer über die neuesten Daten verfügt.
  2. Cache-Invalidierung: Mithilfe von Tags können Sie mit RTK Query definieren, wann bestimmte Daten erneut abgerufen werden sollen. Dadurch bleibt Ihr Cache aktuell, ohne dass Daten manuell aktualisiert werden müssen.
  3. Automatisch generierte Hooks: RTK Query erstellt Hooks für jeden API-Endpunkt, sodass Sie APIs mit einfachen React-Hooks (useGetPostsQuery, useCreatePostMutation usw.) aufrufen können.
  4. Fehlerbehandlung: Beinhaltet eine benutzerdefinierte Fehlerbehandlung durch Middleware, die das Erkennen und Anzeigen von Fehlern erleichtert.
  5. Vereinfachte Redux-Integration: RTK Query lässt sich direkt in Redux integrieren, sodass Sie keine zusätzlichen Bibliotheken für die globale Statusverwaltung oder das Caching benötigen.

RTK-Abfrage vs. React-Abfrage

Sowohl React Query als auch RTK Query bieten Lösungen für das Abrufen und Zwischenspeichern von Daten in React-Anwendungen, haben jedoch unterschiedliche Stärken und Anwendungsfälle:

Feature RTK Query React Query
Purpose Integrated within Redux for managing server data in Redux state. Best for apps already using Redux or requiring centralized global state. Dedicated to managing server state with no Redux dependency. Great for apps focused on server state without Redux.
Caching Automatic caching with fine-grained cache invalidation through tags. Caches data globally within the Redux store. Automatic caching with flexible cache control policies. Maintains a separate cache independent of Redux.
Generated Hooks Auto-generates hooks for endpoints, allowing mutations and queries using useQuery and useMutation hooks. Provides hooks (useQuery, useMutation) that work independently from Redux, but require manual configuration of queries and mutations.
DevTools Integrated into Redux DevTools, making debugging seamless for Redux users. Provides its own React Query DevTools, with detailed insight into query states and cache.
Error Handling Centralized error handling using Redux middleware. Error handling within individual queries, with some centralized error-handling options.
Redux Integration Built directly into Redux, simplifying usage for Redux-based apps. Not integrated with Redux by default, although Redux and React Query can be combined if needed.

Wahl zwischen RTK-Abfrage und Reaktionsabfrage:

  • RTK-Abfrage verwenden wenn:

    • Sie verwenden Redux bereits und möchten eine integrierte, optimierte Lösung für den Datenabruf.
    • Sie benötigen eine zentralisierte Fehlerbehandlung und Devtools-Integration in Redux.
  • React Query verwenden wenn:

    • Sie möchten ein schlankeres Setup ohne Redux-Abhängigkeit.
    • Sie bevorzugen eine separate Serverstatusverwaltung und benötigen keinen globalen App-Status.

Im Wesentlichen eignet sich RTK Query hervorragend für Redux-zentrierte Anwendungen, während React Query Flexibilität und Einfachheit für Projekte ohne Redux oder solche mit einem stärker lokalisierten Fokus auf die Serverstatusverwaltung bietet.


Efficient Data Handling in React Native with RTK Query



1. Speicherkonfiguration und -einrichtung

// src/store/store.js
import AsyncStorage from '@react-native-async-storage/async-storage';
import { combineReducers, configureStore, isRejectedWithValue } from '@reduxjs/toolkit';
import { setupListeners } from '@reduxjs/toolkit/query';
import { FLUSH, PAUSE, PERSIST, persistReducer, PURGE, REGISTER, REHYDRATE } from 'redux-persist';
import { authApi } from '../api/authApi';
import { postsApi } from '../api/postsApi';
import { usersApi } from '../api/usersApi';
import authSlice from '../features/auth/authSlice';

const persistConfig = {
  key: 'root',
  version: 1,
  storage: AsyncStorage,
  blacklist: ['auth', postsApi.middleware, usersApi.middleware, authApi.middleware], // these reduce will not persist data (NOTE: blacklist rtk api slices so that to use tags)
  // whitelist: ['users'], //these reduce will persist data
};

const getEnhancers = (getDefaultEnhancers) => {
  if (process.env.NODE_ENV === 'development') {
    const reactotron = require('../reactotronConfig/ReactotronConfig').default;
    return getDefaultEnhancers().concat(reactotron.createEnhancer());
  }
  return getDefaultEnhancers();
};

/**
 * On api error this will be called
 */
export const rtkQueryErrorLogger = (api) => (next) => (action) => {
  // RTK Query uses `createAsyncThunk` from redux-toolkit under the hood, so we're able to utilize these matchers!
  if (isRejectedWithValue(action)) {
    console.log('isRejectedWithValue', action.error, action.payload);
    alert(JSON.stringify(action)); // This is just an example. You can replace it with your preferred method for displaying notifications.
  }

  return next(action);
};

const reducer = combineReducers({
  auth: authSlice,
  [postsApi.reducerPath]: postsApi.reducer,
  [usersApi.reducerPath]: usersApi.reducer,
  [authApi.reducerPath]: authApi.reducer,
});
const persistedReducer = persistReducer(persistConfig, reducer);

const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    }).concat(postsApi.middleware, usersApi.middleware, authApi.middleware, rtkQueryErrorLogger),
  enhancers: getEnhancers,
});

setupListeners(store.dispatch);

export default store;

  • Redux Store (src/store/store.js): Der Redux Store ist die Hauptstruktur, die den Status der Anwendung speichert. In Ihrem Setup wird es um redux-persist erweitert, um bestimmte Teile des Redux-Status lokal zu speichern, sodass sie auch beim Neustart der App bestehen bleiben.

  • redux-persist:

    • Zweck: Hilft, Teile des Redux-Status über App-Sitzungen hinweg persistent zu halten.
    • Konfiguration: Ein persistConfig-Objekt gibt an, dass auth, postsApi und UsersApi nicht beibehalten (auf die schwarze Liste gesetzt) ​​werden sollen, was bedeutet, dass ihre Daten beim Neustart der App zurückgesetzt werden.
    • persistReducer kombiniert die Reducer-Konfiguration mit der Persistenzfunktionalität.
  • Enhancer: Benutzerdefinierte Enhancer werden verwendet, um Reactotron in den Entwicklungsmodus zu integrieren, ein hilfreiches Tool zum Debuggen von Redux-Aktionen, Status und Netzwerkanforderungen. Dies wird nur in der Entwicklung aktiviert und erleichtert das Debuggen, ohne die Produktion zu beeinträchtigen.

  • Middleware:

    • RTK-Abfrage-Middlewares (postsApi.middleware, usersApi.middleware, authApi.middleware) fügen Funktionen für die automatische Cache-Verwaltung hinzu und machen den Datenabruf effizient.
    • rtkQueryErrorLogger: Eine benutzerdefinierte Middleware protokolliert Fehler, wenn API-Aufrufe fehlschlagen. Es verwendet die isRejectedWithValue-Funktion von RTK Query, um Fehler zu erkennen und zu behandeln, sodass Sie Benutzer auf Probleme aufmerksam machen oder andere Maßnahmen ergreifen können.
  • setupListeners: Diese Funktion ermöglicht das automatische erneute Abrufen von Daten, wenn bestimmte Ereignisse auftreten, z. B. wenn die App den Fokus wiedererlangt oder aus dem Hintergrund fortfährt, sodass Benutzer ohne manuelle Aktualisierung mit neuen Daten versorgt werden.



2. API-Definitionen mit RTK-Abfrage

RTK Query vereinfacht API-Aufrufe durch automatische Generierung von Redux-Slices, Hooks und Caching. Hier ist eine Aufschlüsselung der von Ihnen definierten APIs:

// src/store/store.js
import AsyncStorage from '@react-native-async-storage/async-storage';
import { combineReducers, configureStore, isRejectedWithValue } from '@reduxjs/toolkit';
import { setupListeners } from '@reduxjs/toolkit/query';
import { FLUSH, PAUSE, PERSIST, persistReducer, PURGE, REGISTER, REHYDRATE } from 'redux-persist';
import { authApi } from '../api/authApi';
import { postsApi } from '../api/postsApi';
import { usersApi } from '../api/usersApi';
import authSlice from '../features/auth/authSlice';

const persistConfig = {
  key: 'root',
  version: 1,
  storage: AsyncStorage,
  blacklist: ['auth', postsApi.middleware, usersApi.middleware, authApi.middleware], // these reduce will not persist data (NOTE: blacklist rtk api slices so that to use tags)
  // whitelist: ['users'], //these reduce will persist data
};

const getEnhancers = (getDefaultEnhancers) => {
  if (process.env.NODE_ENV === 'development') {
    const reactotron = require('../reactotronConfig/ReactotronConfig').default;
    return getDefaultEnhancers().concat(reactotron.createEnhancer());
  }
  return getDefaultEnhancers();
};

/**
 * On api error this will be called
 */
export const rtkQueryErrorLogger = (api) => (next) => (action) => {
  // RTK Query uses `createAsyncThunk` from redux-toolkit under the hood, so we're able to utilize these matchers!
  if (isRejectedWithValue(action)) {
    console.log('isRejectedWithValue', action.error, action.payload);
    alert(JSON.stringify(action)); // This is just an example. You can replace it with your preferred method for displaying notifications.
  }

  return next(action);
};

const reducer = combineReducers({
  auth: authSlice,
  [postsApi.reducerPath]: postsApi.reducer,
  [usersApi.reducerPath]: usersApi.reducer,
  [authApi.reducerPath]: authApi.reducer,
});
const persistedReducer = persistReducer(persistConfig, reducer);

const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    }).concat(postsApi.middleware, usersApi.middleware, authApi.middleware, rtkQueryErrorLogger),
  enhancers: getEnhancers,
});

setupListeners(store.dispatch);

export default store;

  • authApi (src/api/authApi.js):
    • Definiert eine Anmeldemutation, die Benutzeranmeldeinformationen (z. B. Benutzername, Passwort) zur Authentifizierung an den Server sendet.
    • onQueryStarted: Sobald die Anmeldung erfolgreich ist, wird das zurückgegebene Token mithilfe der setToken-Aktion in Redux gespeichert. Dies ermöglicht sichere, authentifizierte Anfragen an andere Endpunkte.

// src/api/authApi.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { setToken } from '../features/auth/authSlice';

export const authApi = createApi({
  reducerPath: 'authApi',
  baseQuery: fetchBaseQuery({
    baseUrl: 'https://dummyjson.com/auth/',
  }),
  endpoints: (builder) => ({
    login: builder.mutation({
      query: (credentials) => ({
        url: 'login',
        method: 'POST',
        body: credentials,
      }),
      async onQueryStarted(arg, { dispatch, queryFulfilled }) {
        try {
          const { data } = await queryFulfilled;
          dispatch(setToken(data.accessToken)); // Store the token in Redux
        } catch (error) {
          console.error('Login error:', error);
        }
      },
    }),
  }),
});

export const { useLoginMutation } = authApi;
  • postsApi (src/api/postsApi.js):
    • CRUD-Operationen: Die Posts-API enthält mehrere Endpunkte für die Interaktion mit Posts (Abrufen, Erstellen, Aktualisieren, Löschen).
      • getPosts: Ruft paginierte Beiträge ab, d. h. es ruft Daten in kleineren Blöcken (Seiten) ab und verbessert so die Leistung und Ladezeiten.
      • createPost, updatePost und deletePost: Jeder von ihnen führt eine andere Aktion aus (einen Beitrag erstellen, aktualisieren oder löschen).
    • Tags für das Caching: Jeder Endpunkt verwendet Tags (z. B. { Typ: 'Beiträge', ID }), um die Cache-Invalidierung und -Aktualisierung automatisch zu verwalten. Wenn Sie beispielsweise einen Beitrag erstellen oder löschen, wird der Cache ungültig und getPosts wird aufgefordert, neue Daten ohne manuelles Eingreifen abzurufen.

// src/store/store.js
import AsyncStorage from '@react-native-async-storage/async-storage';
import { combineReducers, configureStore, isRejectedWithValue } from '@reduxjs/toolkit';
import { setupListeners } from '@reduxjs/toolkit/query';
import { FLUSH, PAUSE, PERSIST, persistReducer, PURGE, REGISTER, REHYDRATE } from 'redux-persist';
import { authApi } from '../api/authApi';
import { postsApi } from '../api/postsApi';
import { usersApi } from '../api/usersApi';
import authSlice from '../features/auth/authSlice';

const persistConfig = {
  key: 'root',
  version: 1,
  storage: AsyncStorage,
  blacklist: ['auth', postsApi.middleware, usersApi.middleware, authApi.middleware], // these reduce will not persist data (NOTE: blacklist rtk api slices so that to use tags)
  // whitelist: ['users'], //these reduce will persist data
};

const getEnhancers = (getDefaultEnhancers) => {
  if (process.env.NODE_ENV === 'development') {
    const reactotron = require('../reactotronConfig/ReactotronConfig').default;
    return getDefaultEnhancers().concat(reactotron.createEnhancer());
  }
  return getDefaultEnhancers();
};

/**
 * On api error this will be called
 */
export const rtkQueryErrorLogger = (api) => (next) => (action) => {
  // RTK Query uses `createAsyncThunk` from redux-toolkit under the hood, so we're able to utilize these matchers!
  if (isRejectedWithValue(action)) {
    console.log('isRejectedWithValue', action.error, action.payload);
    alert(JSON.stringify(action)); // This is just an example. You can replace it with your preferred method for displaying notifications.
  }

  return next(action);
};

const reducer = combineReducers({
  auth: authSlice,
  [postsApi.reducerPath]: postsApi.reducer,
  [usersApi.reducerPath]: usersApi.reducer,
  [authApi.reducerPath]: authApi.reducer,
});
const persistedReducer = persistReducer(persistConfig, reducer);

const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    }).concat(postsApi.middleware, usersApi.middleware, authApi.middleware, rtkQueryErrorLogger),
  enhancers: getEnhancers,
});

setupListeners(store.dispatch);

export default store;

  • usersApi (src/api/usersApi.js):
    • Diese API ruft das Profil des authentifizierten Benutzers ab und richtet Autorisierungsheader basierend auf dem Token von Redux ein.
    • Header: PrepareHeaders hängt das Token dynamisch an jede Anfrage an, sofern verfügbar, und ermöglicht so sichere und autorisierte API-Anfragen.


3. Auth-Slice (src/features/auth/authSlice.js)

// src/api/authApi.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { setToken } from '../features/auth/authSlice';

export const authApi = createApi({
  reducerPath: 'authApi',
  baseQuery: fetchBaseQuery({
    baseUrl: 'https://dummyjson.com/auth/',
  }),
  endpoints: (builder) => ({
    login: builder.mutation({
      query: (credentials) => ({
        url: 'login',
        method: 'POST',
        body: credentials,
      }),
      async onQueryStarted(arg, { dispatch, queryFulfilled }) {
        try {
          const { data } = await queryFulfilled;
          dispatch(setToken(data.accessToken)); // Store the token in Redux
        } catch (error) {
          console.error('Login error:', error);
        }
      },
    }),
  }),
});

export const { useLoginMutation } = authApi;
  • authSlice: Ein Redux-Slice verwaltet einen bestimmten Zustand, in diesem Fall die Benutzerauthentifizierung.
  • Statusverwaltung: Der authSlice behält das Token des Benutzers, das für den Zugriff auf geschützte API-Endpunkte verwendet wird.
  • Aktionen:
    • setToken: Speichert das Authentifizierungstoken im Redux-Status.
    • Abmelden: Löscht das Token von Redux und meldet den Benutzer effektiv ab.


4. Reactotron zum Debuggen (src/reactotronConfig/ReactotronConfig.js)

// src/api/postsApi.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

// Define the postsApi slice with RTK Query
export const postsApi = createApi({
  // Unique key for the API slice in Redux state
  reducerPath: 'postsApi',

  // Configure base query settings, including the base URL for all requests
  baseQuery: fetchBaseQuery({
    baseUrl: 'https://jsonplaceholder.typicode.com',
  }),

  // Define cache tag types for automatic cache invalidation
  tagTypes: ['Posts'],

  // Define API endpoints (queries and mutations)
  endpoints: (builder) => ({
    // Query to fetch a paginated list of posts
    getPosts: builder.query({
      // URL and parameters for paginated posts
      query: ({ page = 1, limit = 10 }) => `/posts?_page=${page}&_limit=${limit}`,

      // Tagging posts to automatically refresh this cache when needed
      providesTags: (result) =>
        result
          ? [...result.map(({ id }) => ({ type: 'Posts', id })), { type: 'Posts', id: 'LIST' }]
          : [{ type: 'Posts', id: 'LIST' }],
    }),

    // Query to fetch a single post by its ID
    getPostById: builder.query({
      // Define query with post ID in the URL path
      query: (id) => `/posts/${id}`,

      // Tag individual post by ID for selective cache invalidation
      providesTags: (result, error, id) => [{ type: 'Posts', id }],
    }),

    // Mutation to create a new post
    createPost: builder.mutation({
      // Configure the POST request details and payload
      query: (newPost) => ({
        url: '/posts',
        method: 'POST',
        body: newPost,
      }),

      // Invalidate all posts (paginated list) to refresh after creating a post
      invalidatesTags: [{ type: 'Posts', id: 'LIST' }],
    }),

    // Mutation to update an existing post by its ID
    updatePost: builder.mutation({
      // Define the PUT request with post ID and updated data in the payload
      query: ({ id, ...updatedData }) => ({
        url: `/posts/${id}`,
        method: 'PUT',
        body: updatedData,
      }),

      // Invalidate cache for both the updated post and the paginated list
      invalidatesTags: (result, error, { id }) => [
        { type: 'Posts', id },
        { type: 'Posts', id: 'LIST' },
      ],
    }),

    // Mutation to delete a post by its ID
    deletePost: builder.mutation({
      // Define the DELETE request with post ID in the URL path
      query: (id) => ({
        url: `/posts/${id}`,
        method: 'DELETE',
      }),

      // Invalidate cache for the deleted post and the paginated list
      invalidatesTags: (result, error, id) => [
        { type: 'Posts', id },
        { type: 'Posts', id: 'LIST' },
      ],
    }),
  }),
});

// Export generated hooks for each endpoint to use them in components
export const {
  useGetPostsQuery, // Use this when you want data to be fetched automatically as the component mounts or when the query parameters change.
  useLazyGetPostsQuery, // Use this when you need more control over when the query runs, such as in response to a user action (e.g., clicking a button), conditional fetching, or specific events.
  useGetPostByIdQuery,
  useCreatePostMutation,
  useUpdatePostMutation,
  useDeletePostMutation,
} = postsApi;
  • Reactotron: Reactotron ist ein Debugging-Tool, das dabei hilft, Redux-Statusänderungen zu verfolgen, API-Anfragen zu überwachen und Protokolle zu überprüfen.
  • Setup: Konfiguriert, um console.log-Ausgaben und Redux-Aktionen zu erfassen. Im Entwicklungsmodus bietet dieses Setup eine leistungsstarke Möglichkeit zum Debuggen, ohne zusätzlichen Code hinzuzufügen oder die Produktionsleistung zu verändern.


5. Hauptanwendungskomponenten

// src/api/usersApi.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const usersApi = createApi({
  reducerPath: 'usersApi',
  baseQuery: fetchBaseQuery({
    baseUrl: 'https://dummyjson.com',
    prepareHeaders: (headers, { getState }) => {
      // Get the token from the Redux auth state
      const { token } = getState().auth;

      // If the token exists, set it in the Authorization header
      if (token) {
        headers.set('Authorization', `Bearer ${token}`);
      }

      // Optional: include credentials if needed by the API
      headers.set('credentials', 'include');

      return headers;
    },
  }),
  endpoints: (builder) => ({
    // Fetch user profile with token in Authorization header
    getUserProfile: builder.query({
      query: () => '/auth/me',
    }),
  }),
});

export const { useGetUserProfileQuery } = usersApi;
  • App-Komponente (src/App.js):
    • Die App-Komponente umschließt die gesamte Anwendung in Provider (um Redux verfügbar zu machen) und PersistGate (um das Rendern zu verzögern, bis der persistente Zustand abgerufen wurde).
    • PersistGate sorgt dafür, dass Daten dauerhaft geladen werden, bevor die App angezeigt wird, und reduziert so Inkonsistenzen bei der Ladezeit.

// src/MainApp.js
import React, { useEffect, useState } from 'react';
importieren {
  Aktivitätsindikator,
  Taste,
  FlatList,
  Modal,
  RefreshControl,
  StyleSheet,
  Text,
  Texteingabe,
  Sicht,
} von 'react-native';
import { SafeAreaView } aus 'react-native-safe-area-context';
import { useDispatch, useSelector } from 'react-redux';
import { useLoginMutation } from './api/authApi';
importieren {
  useCreatePostMutation,
  useDeletePostMutation,
  useGetPostsQuery,
  useLazyGetPostsQuery,
  useUpdatePostMutation,
} from './api/postsApi';
import { useGetUserProfileQuery } from './api/usersApi';
importieren {abmelden}von './features/auth/authSlice';

const MainApp = () => {
  const [newPostTitle, setNewPostTitle] = useState('');
  const [page, setPage] = useState(1);
  const [postsData, setPostsData] = useState([]);
  const [refreshing, setRefreshing] = useState(false);
  const [isModalVisible, setModalVisible] = useState(false);

  const distribution = useDispatch();
  const token = useSelector((state) => state.auth.token);

  // Login-Mutation
  const [login, { isLoading: isLoggingIn }] = useLoginMutation();

  // Benutzerprofil abrufen, wenn Token verfügbar ist
  const { data: userProfile, refetch: refetchUserProfile } = useGetUserProfileQuery(undefiniert, {
    überspringen: !token,
  });

  // Paginierte Beiträge abrufen
  const {
    Daten: Beiträge,
    wird geladen,
    isFetching,
    isError,
    erneut abrufen,
  } = useGetPostsQuery({ page, limit: 10 }); // Der useQuery-Hook wird verwendet, wenn Sie Daten beim Laden des Bildschirms abrufen möchten. Rufen Sie beispielsweise das Benutzerprofil auf dem Profilbildschirm ab.
  // Verwenden Sie die Lazy-Abfrage für die Aktualisierung, um Seite 1 direkt abzurufen
  const [triggerFetchFirstPage, { data: lazyData }] = useLazyGetPostsQuery(); // useLazyquery wird verwendet, wenn Sie den API-Aufruf steuern möchten, z. B. beim Klicken auf eine Schaltfläche.

  const [createPost] = useCreatePostMutation();
  const [updatePost] = useUpdatePostMutation();
  const [deletePost] = useDeletePostMutation();

  useEffect(() => {
    if (Beiträge) {
      setPostsData((prevData) => (page === 1 ? posts : [...prevData, ...posts]));
    }
  }, [Beiträge, Seite]);

  // Login-Handler
  const handleLogin = async () => {
    versuchen {
      const credentials = { Benutzername: 'emilys', Passwort: 'emilyspass' };
      Warten Sie auf die Anmeldung (Anmeldeinformationen);
      console.log('userProfile', userProfile);
      refetchUserProfile();
    } Catch (Fehler) {
      console.error('Anmeldung fehlgeschlagen:', Fehler);
    }
  };

  const handleRefresh = async () => {
    setRefreshing(true);
    setPage(1); // Setze die Seite für die nächsten Scrolls auf 1 zurück
    setPostsData([]); // Löschen Sie die Daten, um Duplikate zu vermeiden

    // Den ersten Seitenabruf explizit auslösen
    const { data } = waiting triggerFetchFirstPage({ page: 1, limit: 10 });

    if (Daten) {
      setPostsData(data); // Setze die Beitragsdaten auf die Ergebnisse der ersten Seite
    }

    setRefreshing(false);
  };

  // Einen neuen Beitrag erstellen, ihn oben hinzufügen und die Liste erneut abrufen
  const handleCreatePost = async () => {
    if (newPostTitle) {
      const { data: newPost } = waiting createPost({ title: newPostTitle, body: 'New post content' });
      setNewPostTitle('');
      setPostsData((prevData) => [newPost, ...prevData]);
      refetch();
    }
  };

  // Einen vorhandenen Beitrag aktualisieren und „HASAN“ zum Titel hinzufügen
  const handleUpdatePost = async (post) => {
    const { data: updatePost } = waiting updatePost({
      ID: post.id,
      Titel: `${post.title} HASAN`,
    });
    setPostsData((prevData) =>
      prevData.map((item) => (item?.id === aktualisierterBeitrag?.id ? aktualisierterBeitrag: Artikel))
    );
  };

  // Einen Beitrag löschen und ihn sofort aus der Benutzeroberfläche entfernen
  const handleDeletePost = async (id) => {
    Warten auf deletePost(id);
    setPostsData((prevData) => prevData.filter((post) => post.id !== id));
  };

  // Laden Sie mehr Beiträge für endloses Scrollen
  const loadMorePosts = () => {
    if (!isFetching) {
      setPage((prevPage) => prevPage 1);
    }
  };

  // Modale Sichtbarkeit umschalten
  const toggleModal = () => {
    setModalVisible(!isModalVisible);
  };

  if (isLoading && page === 1) return <Text>Loading...</Text>;
  if (isError) return <Text>Fehler beim Abrufen von Beiträgen.</Text>;

  zurückkehren (
    <SafeAreaView>



<ul>
<li>
<strong>MainApp-Komponente (src/MainApp.js)</strong>:

<ul>
<li>
<strong>Status und Hooks</strong>: Verwaltet lokale Status (z. B. für die Paginierung von Beiträgen) und Hooks wie useLoginMutation, um Aktionen bei bestimmten Ereignissen auszulösen.</li>
<li>
<strong>Anmelden</strong>:

<ul>
<li>Verwendet useLoginMutation, um den Benutzer anzumelden, und löst dann refetchUserProfile aus, um die Benutzerprofildaten zu laden.</li>
<li>
<em>Bedingte Abfrage</em>: Ruft das Benutzerprofil nur ab, wenn ein gültiges Token vorhanden ist (überspringen: !token), wodurch unnötige API-Aufrufe reduziert werden.</li>
</ul>


</li>

<li>

<strong>Beiträge abrufen</strong>:

<ul>
<li>Verwendet useGetPostsQuery zum Abrufen paginierter Beiträge und unterstützt das unendliche Scrollen, indem mehr Daten abgerufen werden, während der Benutzer scrollt.</li>
<li>
<em>Aktualisierungssteuerung</em>: Ermöglicht Benutzern das Aktualisieren der Beitragsliste, nützlich für die Pull-to-Refresh-Funktion auf Mobilgeräten.</li>
</ul>


</li>

<li>

<strong>Beiträge erstellen, aktualisieren, löschen</strong>:

<ul>
<li>
<em>Erstellen</em>: Ruft createPost auf und aktualisiert sofort die Beitragsliste mit dem neuen Beitrag ganz oben.</li>
<li>
<em>Aktualisieren</em>: Hängt beim Aktualisieren „HASAN“ an den Titel eines Beitrags an.</li>
<li>
<em>Löschen</em>: Entfernt einen Beitrag und aktualisiert die Benutzeroberfläche, ohne dass die Seite neu geladen werden muss, dank der Cache-Ungültigmachung von deletePost.</li>
</ul>


</li>

<li>

<strong>UI-Elemente</strong>:

<ul>
<li>Ein Modal zeigt das Benutzerprofil an. Die Profilschaltfläche wird nur angezeigt, wenn Benutzerprofildaten geladen sind, was das Benutzererlebnis verbessert.</li>
</ul>


</li>

<li>

<strong>FlatList</strong>: Zeigt Beiträge in einem scrollbaren, paginierten Format an und verbessert so die Benutzerfreundlichkeit.</li>

</ul>

</li>

</ul>


<hr>

<h2>
  
  
  Zusammenfassung:
</h2>

<p>Ihre React Native-App verwendet <strong>Redux Toolkit (RTK) Query</strong> für effiziente Datenverwaltung und API-Interaktionen. Das Setup umfasst:</p>

<ol>
<li><p><strong>Store-Konfiguration</strong>: Redux-Store mit Redux-Persist zum Speichern spezifischer Daten über App-Sitzungen hinweg, eine benutzerdefinierte Middleware für die Fehlerprotokollierung und Reactotron für das Debuggen im Entwicklungsmodus.</p></li>
<li>
<p><strong>APIs mit RTK-Abfrage</strong>:</p><ul>
<li>
<strong>authApi</strong> übernimmt die Authentifizierung mit einer Login-Mutation und speichert das Token in Redux.</li>
<li>
<strong>postsApi</strong> stellt CRUD-Operationen für Beiträge bereit und verwendet Cache-Tags, um Daten automatisch zu aktualisieren, wenn Beiträge hinzugefügt, aktualisiert oder gelöscht werden.</li>
<li>
<strong>usersApi</strong> ruft das Benutzerprofil mit dynamischen tokenbasierten Autorisierungsheadern ab.</li>
</ul>
</li>
<li><p><strong>Auth Slice</strong>: Verwaltet das Authentifizierungstoken und stellt Aktionen zum Festlegen oder Löschen des Tokens beim Anmelden/Abmelden bereit.</p></li>
<li>
<p><strong>App- und MainApp-Komponenten</strong>:</p>

<ul>
<li>Die Haupt-App verpackt Komponenten in Provider und PersistGate und stellt so sicher, dass der Status vor dem Rendern geladen wird.</li>
<li>
MainApp verwaltet das Abrufen, Erstellen, Aktualisieren und Löschen von Beiträgen. Es lädt Daten bedingt (z. B. ruft das Benutzerprofil nur ab, wenn ein Token vorhanden ist), unterstützt Paginierung und unendliches Scrollen </li>
<li>Verwendet FlatList für eine paginierte Beitragsliste, Modalitäten für das Profil und grundlegende Stile für ein sauberes, organisiertes Layout.</li>
</ul>
</li>
</ol>

<blockquote>
<p>VOLLSTÄNDIGER CODE->



          

            
        

Das obige ist der detaillierte Inhalt vonEffiziente Datenverarbeitung in React Native mit RTK-Abfrage. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn