国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

首頁(yè) web前端 js教程 透過(guò) RTK 查詢?cè)?React Native 中高效處理數(shù)據(jù)

透過(guò) RTK 查詢?cè)?React Native 中高效處理數(shù)據(jù)

Nov 30, 2024 am 10:01 AM

在本指南中,我們將介紹:

  • CRUD 操作
  • 分頁(yè)
  • Redux 透過(guò) RTK 查詢持久化
  • 多個(gè)基本 URL 使用
  • 受保護(hù)與公共路線
  • 快取管理與失效

Efficient Data Handling in React Native with RTK Query

RTK 查詢 是內(nèi)建於 Redux Toolkit (RTK) 中的進(jìn)階資料擷取與快取工具。它透過(guò)為獲取、快取和更新資料等常見(jiàn)任務(wù)產(chǎn)生 Redux 切片和掛鉤來(lái)簡(jiǎn)化 API 互動(dòng)。主要功能包括:

  1. 自動(dòng)快取:RTK Query 快取數(shù)據(jù),並在數(shù)據(jù)失效時(shí)自動(dòng)重新獲取,確保 UI 始終擁有最新數(shù)據(jù)。
  2. 快取失效:RTK 查詢使用標(biāo)籤,讓您定義何時(shí)應(yīng)重新取得某些資料。這有助於保持快取最新,無(wú)需手動(dòng)更新資料。
  3. 自動(dòng)產(chǎn)生的鉤子:RTK Query 為每個(gè) API 端點(diǎn)建立鉤子,讓您可以使用簡(jiǎn)單的 React 鉤子(useGetPostsQuery、useCreatePostMutation 等)呼叫 API。
  4. 錯(cuò)誤處理:包括透過(guò)中間件的自訂錯(cuò)誤處理,可以輕鬆捕獲和顯示錯(cuò)誤。
  5. 簡(jiǎn)化的 Redux 整合:RTK Query 直接與 Redux 集成,因此您不需要額外的函式庫(kù)來(lái)進(jìn)行全域狀態(tài)管理或快取。

RTK 查詢與 React 查詢

React QueryRTK Query 都提供了 React 應(yīng)用程式中的資料取得和快取解決方案,但它們具有不同的優(yōu)勢(shì)和用例:

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.

在 RTK 查詢和 React 查詢之間進(jìn)行選擇:

  • 使用 RTK 查詢如果:

    • 您已經(jīng)在使用 Redux,並且想要一個(gè)整合的、簡(jiǎn)化的資料擷取解決方案。
    • 您需要在 Redux 中進(jìn)行集中式錯(cuò)誤處理和開(kāi)發(fā)工具整合。
  • 使用 React 查詢 如果:

    • 您想要一個(gè)更輕量級(jí)的設(shè)置,無(wú)需 Redux 依賴。
    • 您喜歡單獨(dú)的伺服器狀態(tài)管理,不需要全域應(yīng)用程式狀態(tài)。

本質(zhì)上,RTK Query 非常適合以Redux 為中心的應(yīng)用程序,而React Query 為沒(méi)有Redux 的專案或那些注重本地化伺服器狀態(tài)管理的專案提供了靈活性和簡(jiǎn)單性。


Efficient Data Handling in React Native with RTK Query



1. 商店配置與設(shè)定

// 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):Redux store 是保存應(yīng)用程式狀態(tài)的主要結(jié)構(gòu)。在您的設(shè)定中,它透過(guò) redux-persist 進(jìn)行了增強(qiáng),可以在本地保存 Redux 狀態(tài)的某些部分,因此即使應(yīng)用程式重新啟動(dòng),它們也會(huì)持續(xù)存在。

  • redux-persist:

    • 用途:幫助保持部分 Redux 狀態(tài)在應(yīng)用程式會(huì)話中保持不變。
    • 配置:persistConfig 物件指定 auth、postsApi 和 usersApi 不應(yīng)被持久化(列入黑名單),這表示它們的資料會(huì)在應(yīng)用程式重新啟動(dòng)時(shí)重置。
    • persistReducer 將減速器配置與持久化功能結(jié)合。
  • 增強(qiáng)器:自訂增強(qiáng)器用於在開(kāi)發(fā)模式下整合Reactotron,這是一個(gè)調(diào)試 Redux 操作、狀態(tài)和網(wǎng)路請(qǐng)求的有用工具。這只在開(kāi)發(fā)時(shí)激活,使調(diào)試更容易,而不影響生產(chǎn)。

  • 中介軟體:

    • RTK 查詢中間件(postsApi.middleware、usersApi.middleware、authApi.middleware)新增自動(dòng)快取管理功能,提升資料擷取效率。
    • rtkQueryErrorLogger:自訂中間件在 API 呼叫失敗時(shí)記錄錯(cuò)誤。它使用 RTK Query 的 isRejectedWithValue 函數(shù)來(lái)捕獲和處理錯(cuò)誤,讓您可以提醒使用者有關(guān)問(wèn)題或採(cǎi)取其他操作。
  • setupListeners:此功能可以在發(fā)生某些事件時(shí)自動(dòng)重新獲取數(shù)據(jù),例如當(dāng)應(yīng)用程式重新獲得焦點(diǎn)或從後臺(tái)恢復(fù)時(shí),為用戶提供新鮮數(shù)據(jù),而無(wú)需手動(dòng)重新整理.



2. RTK 查詢的 API 定義

RTK Query 透過(guò)自動(dòng)產(chǎn)生 Redux 切片、掛鉤和快取來(lái)簡(jiǎn)化 API 呼叫。以下是您定義的 API 的詳細(xì)資訊:

// 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):
    • 定義登入突變,將使用者憑證(例如使用者名稱、密碼)傳送到伺服器進(jìn)行身份驗(yàn)證。
    • onQueryStarted:登入成功後,它使用 setToken 操作將傳回的令牌儲(chǔ)存在 Redux 中。這可以實(shí)現(xiàn)對(duì)其他端點(diǎn)的安全性、經(jīng)過(guò)身份驗(yàn)證的請(qǐng)求。

// 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 操作:貼文 API 包含多個(gè)與貼文互動(dòng)的端點(diǎn)(取得、建立、更新、刪除)。
      • getPosts:獲取分頁(yè)帖子,這意味著它以較小的區(qū)塊(頁(yè)面)檢索數(shù)據(jù),從而提高效能和載入時(shí)間。
      • createPost、updatePost 和 deletePost:其中每一個(gè)都執(zhí)行不同的操作(建立、更新或刪除貼文)。
    • 用於快取的標(biāo)籤:每個(gè)端點(diǎn)都使用標(biāo)籤(例如,{ type: 'Posts', id })自動(dòng)管理快取失效和刷新。例如,建立或刪除貼文會(huì)使快取失效,從而提示 getPosts 無(wú)需手動(dòng)幹預(yù)即可取得新資料。

// 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 取得經(jīng)過(guò)驗(yàn)證的使用者的個(gè)人資料,根據(jù) Redux 中的令牌設(shè)定授權(quán)標(biāo)頭。
    • Headers:prepareHeaders 動(dòng)態(tài)地將令牌附加到每個(gè)請(qǐng)求(如果可用),從而允許安全且授權(quán)的 API 請(qǐng)求。


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:Redux 切片管理特定的狀態(tài),在本例中為使用者驗(yàn)證。
  • 狀態(tài)管理:authSlice 保留使用者的令牌,用於存取受保護(hù)的 API 端點(diǎn)。
  • 行動(dòng)
    • setToken:在 Redux 狀態(tài)中儲(chǔ)存身份驗(yàn)證令牌。
    • logout:從 Redux 中清除令牌,有效地將使用者登出。


4. 用於調(diào)試的Reactotron (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 是一個(gè)偵錯(cuò)工具,有助於追蹤 Redux 狀態(tài)變更、監(jiān)控 API 請(qǐng)求和檢查日誌。
  • Setup:配置為捕獲 console.log 輸出和 Redux 操作。在開(kāi)發(fā)模式下,此設(shè)定提供了一種強(qiáng)大的調(diào)試方法,無(wú)需添加額外的程式碼或改變生產(chǎn)效能。


5. 主要應(yīng)用元件

// 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;
  • 應(yīng)用程式元件(src/App.js)
    • App 元件將整個(gè)應(yīng)用程式包裝在 Provider(以使 Redux 可用)和 PersistGate(延遲渲染,直到檢索到持久狀態(tài))。
    • PersistGate 確保在應(yīng)用程式顯示之前持久載入數(shù)據(jù),減少載入時(shí)間不一致。

// src/MainApp.js
從 'react' 導(dǎo)入 React, { useEffect, useState };
進(jìn)口 {
  活動(dòng)指示器,
  按鈕,
  平面列表,
  莫代爾,
  刷新控制,
  樣式表,
  文字,
  文字輸入,
  看法,
來(lái)自 'react-native';
從 'react-native-safe-area-context' 導(dǎo)入 { SafeAreaView } ;
從 'react-redux' 導(dǎo)入 { useDispatch, useSelector };
從 './api/authApi' 導(dǎo)入 { useLoginMutation } ;
進(jìn)口 {
  使用CreatePostMutation,
  使用DeletePostMutation,
  使用GetPosts查詢,
  使用LazyGetPosts查詢,
  使用更新後突變,
來(lái)自 './api/postsApi';
從'./api/usersApi'導(dǎo)入{useGetUserProfileQuery};
導(dǎo)入{註銷}來(lái)自“./features/auth/authSlice”;

const MainApp = () =>; {
  const [newPostTitle, setNewPostTitle] = useState('');
  const [頁(yè)面,setPage] = useState(1);
  const [postsData, setPostsData] = useState([]);
  const [刷新,setRefreshing] = useState(false);
  const [isModalVisible, setModalVisible] = useState(false);

  const 調(diào)度 = useDispatch();
  const token = useSelector((state) => state.auth.token);

  // 登入突變
  const [login, { isLoading: isLoggingIn }] = useLoginMutation();

  // 當(dāng)令牌可用時(shí)取得使用者設(shè)定檔
  const { 資料:userProfile,重新取得:refetchUserProfile } = useGetUserProfileQuery(未定義,{
    跳過(guò):!令牌,
  });

  // 取得分頁(yè)帖子
  常量{
    數(shù)據(jù):帖子,
    正在加載,
    正在獲取,
    是錯(cuò)誤,
    重新獲取,
  } = useGetPostsQuery({ 頁(yè)數(shù), 限制: 10 }); // 當(dāng)你想在螢?zāi)惠d入時(shí)取得資料時(shí),使用 useQuery 鉤子。例如,在個(gè)人資料畫(huà)面上取得使用者個(gè)人資料。
  // 使用惰性查詢刷新直接取得第1頁(yè)
  const [triggerFetchFirstPage,{ 資料:lazyData }] = useLazyGetPostsQuery(); // useLazyquery 當(dāng)你想要控制 api 呼叫時(shí)使用,例如按鈕點(diǎn)擊。

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

  useEffect(() => {
    如果(帖子){
      setPostsData((prevData) => (頁(yè) === 1 ? posts : [...prevData, ...posts]));
    }
  }, [帖子, 頁(yè)]);

  // 登入處理程序
  const handleLogin = async () =>; {
    嘗試 {
      const 憑證 = { 使用者名稱:'emilys',密碼:'emilyspass' };
      等待登入(憑證);
      console.log('使用者設(shè)定檔', 使用者設(shè)定檔);
      重新取得使用者設(shè)定檔();
    } 捕獲(錯(cuò)誤){
      console.error('登入失?。?, error);
    }
  };

  const handleRefresh = async () =>; {
    設(shè)定刷新(真);
    設(shè)定頁(yè)面(1); // 將頁(yè)面重設(shè)為 1 以進(jìn)行下一個(gè)捲動(dòng)
    setPostsData([]); // 清除資料以避免重複

    // 明確觸發(fā)第一頁(yè)獲取
    const { 資料 } = 等待觸發(fā)FetchFirstPage({ 頁(yè)數(shù): 1, 限制: 10 });

    如果(數(shù)據(jù)){
      設(shè)定貼文資料(資料); // 將貼文資料設(shè)定為第一頁(yè)的結(jié)果
    }

    設(shè)定刷新(假);
  };

  // 建立一個(gè)新帖子,將其添加到頂部,然後重新獲取列表
  const handleCreatePost = async () =>; {
    如果(新帖子標(biāo)題){
      const { data: newPost } = wait createPost({ title: newPostTitle, body: '新帖子內(nèi)容' });
      設(shè)定新貼文標(biāo)題('');
      setPostsData((prevData) => [newPost, ...prevData]);
      重新獲取();
    }
  };

  // 更新現(xiàn)有貼文並將「HASAN」新增至其標(biāo)題中
  const handleUpdatePost = async (post) =>; {
    const { 資料:updatePost } = 等待 updatePost({
      id:帖子id,
      標(biāo)題: `${post.title} HASAN`,
    });
    setPostsData((prevData) =>;
      prevData.map((item) => (item?.id === UpdatedPost?.id ?updatedPost : item))
    );
  };

  // 刪除貼文並立即將其從 UI 中刪除
  const handleDeletePost = async (id) =>; {
    等待deletePost(id);
    setPostsData((prevData) => prevData.filter((post) => post.id !== id));
  };

  // 加載更多帖子以實(shí)現(xiàn)無(wú)限滾動(dòng)
  const loadMorePosts = () =>; {
    if (!isFetching) {
      setPage((上一頁(yè)) => 上一頁(yè) 1);
    }
  };

  // 切換模態(tài)可見(jiàn)性
  consttoggleModal = () =>; {
    setModalVisible(!isModalVisible);
  };

  if (isLoading && page === 1) return <text>正在載入...</text>;
  if (isError) return <text> 取得貼文時(shí)發(fā)生錯(cuò)誤。 </text>;

  返回 (
    



  • MainApp 元件 (src/MainApp.js):
    • 狀態(tài)和掛鉤:管理本地狀態(tài)(例如,用於帖子分頁(yè))和諸如 useLoginMutation 之類的掛鉤來(lái)觸發(fā)特定事件的操作。
    • 登入
      • 使用 useLoginMutation 登入用戶,然後觸發(fā) refetchUserProfile 載入用戶設(shè)定檔資料。
      • 條件查詢:只有在有有效令牌時(shí)才取得使用者個(gè)人資料(跳過(guò):!token),減少不必要的 API 呼叫。
    • 取得貼文
      • 使用 useGetPostsQuery 獲取分頁(yè)帖子,透過(guò)在用戶滾動(dòng)時(shí)獲取更多數(shù)據(jù)來(lái)支援無(wú)限滾動(dòng)。
      • 刷新控制項(xiàng):允許用戶刷新貼文列表,對(duì)於行動(dòng)裝置上的下拉式刷新功能很有用。
    • 建立、更新、刪除貼文
      • Create:呼叫createPost,立即更新貼文列表,新貼文位於頂部。
      • 更新:更新時(shí)將「HASAN」附加到貼文標(biāo)題。
      • 刪除:刪除貼文並更新 UI,無(wú)需重新載入頁(yè)面,這要?dú)w功於 deletePost 的快取失效。
    • 使用者介面元素
      • 模態(tài)顯示使用者個(gè)人資料。僅當(dāng)載入使用者設(shè)定檔資料時(shí)才會(huì)出現(xiàn)設(shè)定檔按鈕,從而增強(qiáng)使用者體驗(yàn)。
    • FlatList:以可捲動(dòng)、分頁(yè)格式顯示帖子,增強(qiáng)可用性。

概括:

您的 React Native 應(yīng)用程式使用 Redux Toolkit (RTK) 查詢 來(lái)實(shí)現(xiàn)高效的資料管理和 API 互動(dòng)。設(shè)定包括:

  1. 存儲(chǔ)配置:帶有redux-persist 的Redux 存儲(chǔ),用於跨應(yīng)用程序會(huì)話保存特定數(shù)據(jù),用於錯(cuò)誤日誌記錄的自定義中間件,以及用於在開(kāi)發(fā)模式下進(jìn)行偵錯(cuò)的Reactotron。

  2. 有 RTK 查詢的 API:

    • authApi 透過(guò)登入突變處理驗(yàn)證,將令牌儲(chǔ)存在 Redux 中。
    • postsApi 為貼文提供 CRUD 操作,在新增、更新或刪除貼文時(shí)使用快取標(biāo)籤自動(dòng)刷新資料。
    • usersApi 使用基於動(dòng)態(tài)令牌的授權(quán)標(biāo)頭取得使用者設(shè)定檔。
  3. Auth Slice:管理身分驗(yàn)證令牌並提供在登入/登出時(shí)設(shè)定或清除令牌的操作。

  4. 應(yīng)用程式和主應(yīng)用程式元件

    • 主應(yīng)用程式將元件包裝在 Provider 和 PersistGate 中,確保在渲染之前載入狀態(tài)。
    • MainApp 管理貼文的取得、建立、更新和刪除。它有條件地載入資料(例如,僅當(dāng)令牌存在時(shí)才取得使用者設(shè)定檔),支援分頁(yè)和無(wú)限滾動(dòng)
    • 使用 FlatList 作為分頁(yè)貼文列表,使用模式作為個(gè)人資料,並使用基本樣式來(lái)實(shí)現(xiàn)乾淨(jìng)、有組織的佈局。

完整程式碼->

以上是透過(guò) RTK 查詢?cè)?React Native 中高效處理數(shù)據(jù)的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願(yuàn)投稿,版權(quán)歸原作者所有。本站不承擔(dān)相應(yīng)的法律責(zé)任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請(qǐng)聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費(fèi)脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強(qiáng)大的PHP整合開(kāi)發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級(jí)程式碼編輯軟體(SublimeText3)

熱門(mén)話題

Java vs. JavaScript:清除混亂 Java vs. JavaScript:清除混亂 Jun 20, 2025 am 12:27 AM

Java和JavaScript是不同的編程語(yǔ)言,各自適用於不同的應(yīng)用場(chǎng)景。 Java用於大型企業(yè)和移動(dòng)應(yīng)用開(kāi)發(fā),而JavaScript主要用於網(wǎng)頁(yè)開(kāi)發(fā)。

JavaScript評(píng)論:簡(jiǎn)短說(shuō)明 JavaScript評(píng)論:簡(jiǎn)短說(shuō)明 Jun 19, 2025 am 12:40 AM

JavascriptconcommentsenceenceEncorenceEnterential gransimenting,reading and guidingCodeeXecution.1)單inecommentsareusedforquickexplanations.2)多l(xiāng)inecommentsexplaincomplexlogicorprovideDocumentation.3)

如何在JS中與日期和時(shí)間合作? 如何在JS中與日期和時(shí)間合作? Jul 01, 2025 am 01:27 AM

JavaScript中的日期和時(shí)間處理需注意以下幾點(diǎn):1.創(chuàng)建Date對(duì)像有多種方式,推薦使用ISO格式字符串以保證兼容性;2.獲取和設(shè)置時(shí)間信息可用get和set方法,注意月份從0開(kāi)始;3.手動(dòng)格式化日期需拼接字符串,也可使用第三方庫(kù);4.處理時(shí)區(qū)問(wèn)題建議使用支持時(shí)區(qū)的庫(kù),如Luxon。掌握這些要點(diǎn)能有效避免常見(jiàn)錯(cuò)誤。

JavaScript與Java:開(kāi)發(fā)人員的全面比較 JavaScript與Java:開(kāi)發(fā)人員的全面比較 Jun 20, 2025 am 12:21 AM

JavaScriptIspreferredforredforwebdevelverment,而Javaisbetterforlarge-ScalebackendsystystemsandSandAndRoidApps.1)JavascriptexcelcelsincreatingInteractiveWebexperienceswebexperienceswithitswithitsdynamicnnamicnnamicnnamicnnamicnemicnemicnemicnemicnemicnemicnemicnemicnddommanipulation.2)

為什麼要將標(biāo)籤放在的底部? 為什麼要將標(biāo)籤放在的底部? Jul 02, 2025 am 01:22 AM

PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl

JavaScript:探索用於高效編碼的數(shù)據(jù)類型 JavaScript:探索用於高效編碼的數(shù)據(jù)類型 Jun 20, 2025 am 12:46 AM

javascripthassevenfundaMentalDatatypes:數(shù)字,弦,布爾值,未定義,null,object和symbol.1)numberSeadUble-eaduble-ecisionFormat,forwidevaluerangesbutbecautious.2)

什麼是在DOM中冒泡和捕獲的事件? 什麼是在DOM中冒泡和捕獲的事件? Jul 02, 2025 am 01:19 AM

事件捕獲和冒泡是DOM中事件傳播的兩個(gè)階段,捕獲是從頂層向下到目標(biāo)元素,冒泡是從目標(biāo)元素向上傳播到頂層。 1.事件捕獲通過(guò)addEventListener的useCapture參數(shù)設(shè)為true實(shí)現(xiàn);2.事件冒泡是默認(rèn)行為,useCapture設(shè)為false或省略;3.可使用event.stopPropagation()阻止事件傳播;4.冒泡支持事件委託,提高動(dòng)態(tài)內(nèi)容處理效率;5.捕獲可用於提前攔截事件,如日誌記錄或錯(cuò)誤處理。了解這兩個(gè)階段有助於精確控制JavaScript響應(yīng)用戶操作的時(shí)機(jī)和方式。

Java和JavaScript有什麼區(qū)別? Java和JavaScript有什麼區(qū)別? Jun 17, 2025 am 09:17 AM

Java和JavaScript是不同的編程語(yǔ)言。 1.Java是靜態(tài)類型、編譯型語(yǔ)言,適用於企業(yè)應(yīng)用和大型系統(tǒng)。 2.JavaScript是動(dòng)態(tài)類型、解釋型語(yǔ)言,主要用於網(wǎng)頁(yè)交互和前端開(kāi)發(fā)。

See all articles