Rumah >hujung hadapan web >tutorial js >Pengendalian Data Cekap dalam React Native dengan Pertanyaan RTK

Pengendalian Data Cekap dalam React Native dengan Pertanyaan RTK

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-11-30 10:01:14950semak imbas

Dalam panduan ini, kami akan membincangkan:

  • Operasi CRUD
  • Penomboran
  • Redux Berterusan dengan Pertanyaan RTK
  • Penggunaan URL Berbilang Asas
  • Laluan Terlindung dan Awam
  • Pengurusan dan Pembatalan Cache

Efficient Data Handling in React Native with RTK Query

Pertanyaan RTK ialah alat pengambilan data dan caching termaju yang terbina dalam Redux Toolkit (RTK). Ia menyelaraskan interaksi API dengan menjana hirisan dan cangkuk Redux untuk tugas biasa seperti mengambil, menyimpan cache dan mengemas kini data. Ciri utama termasuk:

  1. Caching Automatik: RTK Query cache data dan ambil semula secara automatik apabila data tidak sah, memastikan UI sentiasa mempunyai data terkini.
  2. Pentaksahihan Cache: Menggunakan teg, Pertanyaan RTK membolehkan anda menentukan bila data tertentu perlu diambil semula. Ini membantu memastikan cache anda sentiasa segar tanpa mengemas kini data secara manual.
  3. Cangkuk Dijana Auto: Pertanyaan RTK mencipta cangkuk untuk setiap titik akhir API, membolehkan anda memanggil API menggunakan cangkuk React yang mudah (useGetPostsQuery, useCreatePostMutation, dll.).
  4. Pengendalian Ralat: Termasuk pengendalian ralat tersuai melalui perisian tengah, menjadikannya mudah untuk menangkap dan memaparkan ralat.
  5. Penyepaduan Redux Ringkas: RTK Query disepadukan terus dengan Redux, jadi anda tidak memerlukan perpustakaan tambahan untuk pengurusan keadaan global atau caching.

Pertanyaan RTK lwn. Pertanyaan Reaksi

Kedua-dua React Query dan RTK Query menyediakan penyelesaian untuk pengambilan data dan caching dalam aplikasi React, tetapi mereka mempunyai kekuatan dan kes penggunaan yang berbeza:

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.

Memilih Antara Pertanyaan RTK dan Pertanyaan Reaksi:

  • Gunakan Pertanyaan RTK jika:

    • Anda sudah menggunakan Redux dan mahukan penyelesaian bersepadu dan diperkemas untuk pengambilan data.
    • Anda memerlukan pengendalian ralat terpusat dan penyepaduan devtools dalam Redux.
  • Gunakan React Query jika:

    • Anda mahukan persediaan yang lebih ringan tanpa pergantungan Redux.
    • Anda lebih suka pengurusan keadaan pelayan yang berasingan dan tidak memerlukan keadaan apl global.

Pada dasarnya, RTK Query cemerlang untuk aplikasi Redux-centric, manakala React Query memberikan fleksibiliti dan kesederhanaan untuk projek tanpa Redux atau yang mempunyai fokus pengurusan keadaan pelayan yang lebih setempat.


Efficient Data Handling in React Native with RTK Query



1. Tatarajah dan Persediaan Stor

// 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;

  • Stor Redux (src/store/store.js): Stor Redux ialah struktur utama yang memegang keadaan aplikasi. Dalam persediaan anda, ia dipertingkatkan dengan redux-persist untuk menyimpan bahagian tertentu keadaan Redux secara setempat, supaya ia berterusan walaupun apabila apl dimulakan semula.

  • redux-berterusan:

    • Tujuan: Membantu mengekalkan bahagian keadaan Redux berterusan merentas sesi apl.
    • Konfigurasi: Objek persistConfig menentukan bahawa auth, postsApi dan usersApi tidak boleh diteruskan (disenarai hitam), bermakna data mereka ditetapkan semula semasa aplikasi dimulakan semula.
    • persistReducer menggabungkan konfigurasi pengurang dengan fungsi kegigihan.
  • Peningkatan: Penambah tersuai digunakan untuk menyepadukan Reactotron dalam mod pembangunan, alat yang berguna untuk menyahpepijat tindakan Redux, keadaan dan permintaan rangkaian. Ini hanya diaktifkan dalam pembangunan, menjadikan penyahpepijatan lebih mudah tanpa menjejaskan pengeluaran.

  • Perisian Tengah:

    • Perisian tengah Pertanyaan RTK (postsApi.middleware, usersApi.middleware, authApi.middleware) menambah fungsi untuk pengurusan cache automatik, menjadikan pengambilan data cekap.
    • rtkQueryErrorLogger: Perisian tengah tersuai mencatatkan ralat apabila panggilan API gagal. Ia menggunakan fungsi isRejectedWithValue RTK Query untuk menangkap dan mengendalikan ralat, membolehkan anda memaklumkan pengguna tentang isu atau mengambil tindakan lain.
  • setupListeners: Fungsi ini mendayakan pengambilan semula data secara automatik apabila peristiwa tertentu berlaku, seperti apabila apl mendapat semula fokus atau menyambung semula dari latar belakang, memberikan pengguna data baharu tanpa muat semula manual.



2. Takrifan API dengan Pertanyaan RTK

Pertanyaan RTK memudahkan panggilan API dengan menjana hirisan, cangkuk dan caching Redux secara automatik. Berikut ialah pecahan API yang anda tetapkan:

// 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):
    • Mentakrifkan mutasi log masuk yang menghantar bukti kelayakan pengguna (cth., nama pengguna, kata laluan) ke pelayan untuk mengesahkan.
    • onQueryStarted: Setelah log masuk berjaya, ia menyimpan token yang dikembalikan dalam Redux menggunakan tindakan setToken. Ini membolehkan permintaan yang selamat dan disahkan ke titik akhir yang lain.

// 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):
    • Operasi CRUD: API siaran mengandungi berbilang titik akhir untuk berinteraksi dengan siaran (ambil, buat, kemas kini, padam).
      • getPosts: Mengambil siaran bernombor, bermakna ia mendapatkan semula data dalam ketulan (halaman) yang lebih kecil, meningkatkan prestasi dan masa pemuatan.
      • createPost, updatePost dan deletePost: Setiap satu daripada ini melakukan tindakan yang berbeza (buat, kemas kini atau padamkan siaran).
    • Teg untuk Cache: Setiap titik akhir menggunakan teg (cth., { type: 'Posts', id }) untuk mengurus pembatalan dan penyegaran cache secara automatik. Contohnya, membuat atau memadamkan siaran membatalkan cache, menggesa getPosts untuk mengambil data baharu tanpa campur tangan manual.

// 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):
    • API ini mengambil profil pengguna yang disahkan, menyediakan pengepala Keizinan berdasarkan token daripada Redux.
    • Pengepala: prepareHeaders secara dinamik melampirkan token pada setiap permintaan jika tersedia, membenarkan permintaan API yang selamat dan dibenarkan.


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: Potongan Redux menguruskan bahagian tertentu keadaan, dalam kes ini, pengesahan pengguna.
  • Pengurusan Negeri: AuthSlice menyimpan token pengguna, yang digunakan untuk mengakses titik akhir API yang dilindungi.
  • Tindakan:
    • setToken: Menyimpan token pengesahan dalam keadaan Redux.
    • log keluar: Kosongkan token daripada Redux, log keluar pengguna dengan berkesan.


4. Reactotron untuk Penyahpepijatan (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 ialah alat penyahpepijatan yang membantu menjejaki perubahan keadaan Redux, memantau permintaan API dan memeriksa log.
  • Persediaan: Dikonfigurasikan untuk menangkap output console.log dan tindakan Redux. Dalam mod pembangunan, persediaan ini menyediakan cara yang berkesan untuk nyahpepijat tanpa menambah kod tambahan atau mengubah prestasi pengeluaran.


5. Komponen Aplikasi Utama

// 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;
  • Komponen Apl (src/App.js):
    • Komponen Apl membungkus keseluruhan aplikasi dalam Pembekal (untuk menjadikan Redux tersedia) dan PersistGate (untuk menangguhkan pemaparan sehingga keadaan berterusan telah diambil semula).
    • PersistGate memastikan pemuatan data berterusan sebelum apl dipaparkan, mengurangkan ketidakkonsistenan masa muat.

// src/MainApp.js
import React, { useEffect, useState } daripada 'react';
import {
  Penunjuk Aktiviti,
  butang,
  Senarai Rata,
  modal,
  RefreshControl,
  Stylesheet,
  teks,
  TextInput,
  Lihat,
} daripada 'react-native';
import { SafeAreaView } daripada 'react-native-safe-area-context';
import { useDispatch, useSelector } daripada 'react-redux';
import { useLoginMutation } daripada './api/authApi';
import {
  gunakanCreatePostMutation,
  gunakanDeletePostMutation,
  gunakanGetPostsQuery,
  gunakanLazyGetPostsQuery,
  useUpdatePostMutation,
} daripada './api/postsApi';
import { useGetUserProfileQuery } daripada './api/usersApi';
import { logout }daripada './features/auth/authSlice';

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

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

  // Mutasi log masuk
  const [log masuk, { isLoading: isLoggingIn }] = useLoginMutation();

  // Ambil profil pengguna apabila token tersedia
  const { data: userProfile, refetch: refetchUserProfile } = useGetUserProfileQuery(undefined, {
    langkau: !token,
  });

  // Ambil catatan bernombor
  const {
    data: siaran,
    sedang memuatkan,
    isFetching,
    isError,
    ulang semula,
  } = useGetPostsQuery({halaman, had: 10}); // Cangkuk useQuery digunakan apabila anda ingin mengambil data pada beban skrin. Contohnya ambil profil pengguna pada skrin profil.
  // Gunakan pertanyaan malas untuk muat semula untuk terus mengambil halaman 1
  const [triggerFetchFirstPage, { data: lazyData }] = useLazyGetPostsQuery(); // useLazyquery digunakan apabila anda ingin mengawal panggilan api, seperti pada klik butang.

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

  useEffect(() => {
    jika (siaran) {
      setPostsData((prevData) => (halaman === 1 ? siaran : [...prevData, ...posts]));
    }
  }, [siaran, halaman]);

  // Pengendali log masuk
  const handleLogin = async () => {
    cuba {
      kelayakan const = { nama pengguna: 'emilys', kata laluan: 'emilyspass' };
      tunggu log masuk(kredential);
      console.log('userProfile', userProfile);
      refetchUserProfile();
    } tangkap (ralat) {
      console.error('Log masuk gagal:', ralat);
    }
  };

  const handleRefresh = tak segerak () => {
    setRefreshing(true);
    setPage(1); // Tetapkan semula halaman kepada 1 untuk skrol seterusnya
    setPostsData([]); // Kosongkan data untuk mengelakkan pertindihan

    // Cetuskan pengambilan halaman pertama secara eksplisit
    const { data } = menunggu triggerFetchFirstPage({halaman: 1, had: 10});

    jika (data) {
      setPostsData(data); // Tetapkan data siaran kepada hasil halaman pertama
    }

    setRefreshing(false);
  };

  // Cipta siaran baharu, tambahkannya ke bahagian atas dan dapatkan semula senarai
  const handleCreatePost = tak segerak () => {
    if (newPostTitle) {
      const { data: newPost } = tunggu createPost({ title: newPostTitle, body: 'New post content' });
      setNewPostTitle('');
      setPostsData((prevData) => [newPost, ...prevData]);
      ulang ();
    }
  };

  // Kemas kini siaran sedia ada dan tambah "HASAN" pada tajuknya
  const handleUpdatePost = async (siaran) => {
    const { data: updatedPost } = tunggu updatePost({
      id: post.id,
      tajuk: `${post.title} HASAN`,
    });
    setPostsData((prevData) =>
      prevData.map((item) => (item?.id === updatedPost?.id ? updatedPost : item))
    );
  };

  // Padamkan siaran dan alih keluarnya daripada UI dengan serta-merta
  const handleDeletePost = async (id) => {
    tunggu deletePost(id);
    setPostsData((prevData) => prevData.filter((post) => post.id !== id));
  };

  // Muatkan lebih banyak siaran untuk menatal tanpa had
  const loadMorePosts = () => {
    jika (!isFetching) {
      setPage((prevPage) => prevPage 1);
    }
  };

  // Togol keterlihatan modal
  const toggleModal = () => {
    setModalVisible(!isModalVisible);
  };

  jika (sedangMemuatkan && halaman === 1) kembalikan <Teks>Memuatkan...</Teks>;
  jika (isError) mengembalikan <Teks>Ralat semasa mengambil siaran.</Teks>;

  kembali (
    <SafeAreaView>



<ul>
<li>
<strong>Komponen Aplikasi Utama (src/MainApp.js)</strong>:

<ul>
<li>
<strong>Keadaan dan Cangkuk</strong>: Menguruskan keadaan setempat (cth., untuk penomboran catatan) dan cangkuk seperti useLoginMutation untuk mencetuskan tindakan pada acara tertentu.</li>
<li>
<strong>Log Masuk</strong>:

<ul>
<li>Menggunakan useLoginMutation untuk log masuk pengguna dan kemudian mencetuskan refetchUserProfile untuk memuatkan data profil pengguna.</li>
<li>
<em>Pertanyaan Bersyarat</em>: Hanya mengambil profil pengguna apabila token yang sah wujud (langkau: !token), mengurangkan panggilan API yang tidak diperlukan.</li>
</ul>


</li>

<li>

<strong>Mengambil Siaran</strong>:

<ul>
<li>Menggunakan useGetPostsQuery untuk mengambil siaran bernombor, menyokong penatalan tidak terhingga dengan mengambil lebih banyak data semasa pengguna menatal.</li>
<li>
<em>Kawalan Segar Semula</em>: Membenarkan pengguna memuat semula senarai siaran, berguna untuk fungsi tarik-untuk-segar semula pada mudah alih.</li>
</ul>


</li>

<li>

<strong>Buat, Kemas Kini, Padam Catatan</strong>:

<ul>
<li>
<em>Buat</em>: Panggil createPost, serta-merta mengemas kini senarai siaran dengan siaran baharu di bahagian atas.</li>
<li>
<em>Kemas kini</em>: Menambahkan "HASAN" pada tajuk siaran apabila dikemas kini.</li>
<li>
<em>Padam</em>: Mengalih keluar siaran dan mengemas kini UI tanpa memerlukan muat semula halaman, terima kasih kepada ketidaksahihan cache daripada deletePost.</li>
</ul>


</li>

<li>

<strong>Elemen UI</strong>:

<ul>
<li>Satu modal memaparkan profil pengguna. Butang profil hanya muncul jika data Profil pengguna dimuatkan, meningkatkan pengalaman pengguna.</li>
</ul>


</li>

<li>

<strong>FlatList</strong>: Memaparkan siaran dalam format yang boleh ditatal, dinomborkan, meningkatkan kebolehgunaan.</li>

</ul>

</li>

</ul>


<hr>

<h2>
  
  
  Ringkasan:
</h2>

<p>Apl React Native anda menggunakan <strong>Pertanyaan Redux Toolkit (RTK)</strong> untuk pengurusan data yang cekap dan interaksi API. Persediaan termasuk:</p>

<ol>
<li><p><strong>Konfigurasi Kedai</strong>: Simpan Redux dengan redux-berterusan untuk menyimpan data khusus merentas sesi apl, perisian tengah tersuai untuk pengelogan ralat dan Reactotron untuk nyahpepijat dalam mod pembangunan.</p></li>
<li>
<p><strong>API dengan RTK Query</strong>:</p><ul>
<li>
<strong>authApi</strong> mengendalikan pengesahan dengan mutasi log masuk, menyimpan token dalam Redux.</li>
<li>
<strong>postsApi</strong> menyediakan operasi CRUD untuk siaran, menggunakan teg cache untuk memuat semula data secara automatik apabila siaran ditambah, dikemas kini atau dipadamkan.</li>
<li>
<strong>usersApi</strong> mengambil profil pengguna dengan pengepala kebenaran berasaskan token dinamik.</li>
</ul>
</li>
<li><p><strong>Auth Slice</strong>: Menguruskan token pengesahan dan menyediakan tindakan untuk menetapkan atau mengosongkan token semasa log masuk/log keluar.</p></li>
<li>
<p><strong>Komponen Apl dan Apl Utama</strong>:</p>

<ul>
<li>Apl utama membungkus komponen dalam Provider dan PersistGate, memastikan keadaan dimuatkan sebelum dipaparkan.</li>
<li>
MainApp mengurus pengambilan, mencipta, mengemas kini dan memadamkan siaran. Ia memuatkan data secara bersyarat (cth., mengambil profil pengguna hanya apabila token wujud), menyokong penomboran dan penatalan tak terhingga </li>
<li>Menggunakan FlatList untuk senarai siaran bernombor, modal untuk profil dan gaya asas untuk susun atur yang bersih dan teratur.</li>
</ul>
</li>
</ol>

<blockquote>
<p>KOD PENUH->



          

            
        

Atas ialah kandungan terperinci Pengendalian Data Cekap dalam React Native dengan Pertanyaan RTK. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn