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

Pengendalian Data Cekap dalam React Native dengan Pertanyaan RTK

Nov 30, 2024 am 10:01 AM

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;

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
  • 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;

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
  • 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;
Salin selepas log masuk
Salin selepas log masuk
  • 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;

Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk
  • 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;
Salin selepas log masuk
Salin selepas log masuk
  • 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;
Salin selepas log masuk
  • 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;
Salin selepas log masuk
  • 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->



          

            
        
Salin selepas log masuk

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 Laman Web ini
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

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

<🎜>: Bubble Gum Simulator Infinity - Cara Mendapatkan dan Menggunakan Kekunci Diraja
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Sistem Fusion, dijelaskan
4 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers of the Witch Tree - Cara Membuka Kunci Cangkuk Bergelut
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Tutorial Java
1672
14
Tutorial PHP
1276
29
Tutorial C#
1256
24
Python vs JavaScript: Keluk Pembelajaran dan Kemudahan Penggunaan Python vs JavaScript: Keluk Pembelajaran dan Kemudahan Penggunaan Apr 16, 2025 am 12:12 AM

Python lebih sesuai untuk pemula, dengan lengkung pembelajaran yang lancar dan sintaks ringkas; JavaScript sesuai untuk pembangunan front-end, dengan lengkung pembelajaran yang curam dan sintaks yang fleksibel. 1. Sintaks Python adalah intuitif dan sesuai untuk sains data dan pembangunan back-end. 2. JavaScript adalah fleksibel dan digunakan secara meluas dalam pengaturcaraan depan dan pelayan.

Dari C/C ke JavaScript: Bagaimana semuanya berfungsi Dari C/C ke JavaScript: Bagaimana semuanya berfungsi Apr 14, 2025 am 12:05 AM

Peralihan dari C/C ke JavaScript memerlukan menyesuaikan diri dengan menaip dinamik, pengumpulan sampah dan pengaturcaraan asynchronous. 1) C/C adalah bahasa yang ditaip secara statik yang memerlukan pengurusan memori manual, manakala JavaScript ditaip secara dinamik dan pengumpulan sampah diproses secara automatik. 2) C/C perlu dikumpulkan ke dalam kod mesin, manakala JavaScript adalah bahasa yang ditafsirkan. 3) JavaScript memperkenalkan konsep seperti penutupan, rantaian prototaip dan janji, yang meningkatkan keupayaan pengaturcaraan fleksibiliti dan asynchronous.

JavaScript dan Web: Fungsi teras dan kes penggunaan JavaScript dan Web: Fungsi teras dan kes penggunaan Apr 18, 2025 am 12:19 AM

Penggunaan utama JavaScript dalam pembangunan web termasuk interaksi klien, pengesahan bentuk dan komunikasi tak segerak. 1) kemas kini kandungan dinamik dan interaksi pengguna melalui operasi DOM; 2) pengesahan pelanggan dijalankan sebelum pengguna mengemukakan data untuk meningkatkan pengalaman pengguna; 3) Komunikasi yang tidak bersesuaian dengan pelayan dicapai melalui teknologi Ajax.

JavaScript in Action: Contoh dan projek dunia nyata JavaScript in Action: Contoh dan projek dunia nyata Apr 19, 2025 am 12:13 AM

Aplikasi JavaScript di dunia nyata termasuk pembangunan depan dan back-end. 1) Memaparkan aplikasi front-end dengan membina aplikasi senarai TODO, yang melibatkan operasi DOM dan pemprosesan acara. 2) Membina Restfulapi melalui Node.js dan menyatakan untuk menunjukkan aplikasi back-end.

Memahami Enjin JavaScript: Butiran Pelaksanaan Memahami Enjin JavaScript: Butiran Pelaksanaan Apr 17, 2025 am 12:05 AM

Memahami bagaimana enjin JavaScript berfungsi secara dalaman adalah penting kepada pemaju kerana ia membantu menulis kod yang lebih cekap dan memahami kesesakan prestasi dan strategi pengoptimuman. 1) aliran kerja enjin termasuk tiga peringkat: parsing, penyusun dan pelaksanaan; 2) Semasa proses pelaksanaan, enjin akan melakukan pengoptimuman dinamik, seperti cache dalam talian dan kelas tersembunyi; 3) Amalan terbaik termasuk mengelakkan pembolehubah global, mengoptimumkan gelung, menggunakan const dan membiarkan, dan mengelakkan penggunaan penutupan yang berlebihan.

Python vs JavaScript: Komuniti, Perpustakaan, dan Sumber Python vs JavaScript: Komuniti, Perpustakaan, dan Sumber Apr 15, 2025 am 12:16 AM

Python dan JavaScript mempunyai kelebihan dan kekurangan mereka sendiri dari segi komuniti, perpustakaan dan sumber. 1) Komuniti Python mesra dan sesuai untuk pemula, tetapi sumber pembangunan depan tidak kaya dengan JavaScript. 2) Python berkuasa dalam bidang sains data dan perpustakaan pembelajaran mesin, sementara JavaScript lebih baik dalam perpustakaan pembangunan dan kerangka pembangunan depan. 3) Kedua -duanya mempunyai sumber pembelajaran yang kaya, tetapi Python sesuai untuk memulakan dengan dokumen rasmi, sementara JavaScript lebih baik dengan MDNWebDocs. Pilihan harus berdasarkan keperluan projek dan kepentingan peribadi.

Python vs JavaScript: Persekitaran dan Alat Pembangunan Python vs JavaScript: Persekitaran dan Alat Pembangunan Apr 26, 2025 am 12:09 AM

Kedua -dua pilihan Python dan JavaScript dalam persekitaran pembangunan adalah penting. 1) Persekitaran pembangunan Python termasuk Pycharm, Jupyternotebook dan Anaconda, yang sesuai untuk sains data dan prototaip cepat. 2) Persekitaran pembangunan JavaScript termasuk node.js, vscode dan webpack, yang sesuai untuk pembangunan front-end dan back-end. Memilih alat yang betul mengikut keperluan projek dapat meningkatkan kecekapan pembangunan dan kadar kejayaan projek.

Peranan C/C dalam JavaScript Jurubah dan Penyusun Peranan C/C dalam JavaScript Jurubah dan Penyusun Apr 20, 2025 am 12:01 AM

C dan C memainkan peranan penting dalam enjin JavaScript, terutamanya digunakan untuk melaksanakan jurubahasa dan penyusun JIT. 1) C digunakan untuk menghuraikan kod sumber JavaScript dan menghasilkan pokok sintaks abstrak. 2) C bertanggungjawab untuk menjana dan melaksanakan bytecode. 3) C melaksanakan pengkompil JIT, mengoptimumkan dan menyusun kod hot-spot semasa runtime, dan dengan ketara meningkatkan kecekapan pelaksanaan JavaScript.

See all articles