首頁 web前端 js教程 透過 RTK 查詢在 React Native 中高效處理數據

透過 RTK 查詢在 React Native 中高效處理數據

Nov 30, 2024 am 10:01 AM

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

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

Efficient Data Handling in React Native with RTK Query

RTK 查詢 是內建於 Redux Toolkit (RTK) 中的進階資料擷取與快取工具。它透過為獲取、快取和更新資料等常見任務產生 Redux 切片和掛鉤來簡化 API 互動。主要功能包括:

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

RTK 查詢與 React 查詢

React QueryRTK Query 都提供了 React 應用程式中的資料取得和快取解決方案,但它們具有不同的優勢和用例:

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 查詢之間進行選擇:

  • 使用 RTK 查詢如果:

    • 您已經在使用 Redux,並且想要一個整合的、簡化的資料擷取解決方案。
    • 您需要在 Redux 中進行集中式錯誤處理和開發工具整合。
  • 使用 React 查詢 如果:

    • 您想要一個更輕量級的設置,無需 Redux 依賴。
    • 您喜歡單獨的伺服器狀態管理,不需要全域應用程式狀態。

本質上,RTK Query 非常適合以Redux 為中心的應用程序,而React Query 為沒有Redux 的專案或那些注重本地化伺服器狀態管理的專案提供了靈活性和簡單性。


Efficient Data Handling in React Native with RTK Query



1. 商店配置與設定

// 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 是保存應用程式狀態的主要結構。在您的設定中,它透過 redux-persist 進行了增強,可以在本地保存 Redux 狀態的某些部分,因此即使應用程式重新啟動,它們也會持續存在。

  • redux-persist:

    • 用途:幫助保持部分 Redux 狀態在應用程式會話中保持不變。
    • 配置:persistConfig 物件指定 auth、postsApi 和 usersApi 不應被持久化(列入黑名單),這表示它們的資料會在應用程式重新啟動時重置。
    • persistReducer 將減速器配置與持久化功能結合。
  • 增強器:自訂增強器用於在開發模式下整合Reactotron,這是一個調試 Redux 操作、狀態和網路請求的有用工具。這只在開發時激活,使調試更容易,而不影響生產。

  • 中介軟體:

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



2. RTK 查詢的 API 定義

RTK Query 透過自動產生 Redux 切片、掛鉤和快取來簡化 API 呼叫。以下是您定義的 API 的詳細資訊:

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

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

// 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 取得經過驗證的使用者的個人資料,根據 Redux 中的令牌設定授權標頭。
    • Headers:prepareHeaders 動態地將令牌附加到每個請求(如果可用),從而允許安全且授權的 API 請求。


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 切片管理特定的狀態,在本例中為使用者驗證。
  • 狀態管理:authSlice 保留使用者的令牌,用於存取受保護的 API 端點。
  • 行動
    • setToken:在 Redux 狀態中儲存身份驗證令牌。
    • logout:從 Redux 中清除令牌,有效地將使用者登出。


4. 用於調試的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 是一個偵錯工具,有助於追蹤 Redux 狀態變更、監控 API 請求和檢查日誌。
  • Setup:配置為捕獲 console.log 輸出和 Redux 操作。在開發模式下,此設定提供了一種強大的調試方法,無需添加額外的程式碼或改變生產效能。


5. 主要應用元件

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

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

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

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

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

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

  // 取得分頁帖子
  常量{
    數據:帖子,
    正在加載,
    正在獲取,
    是錯誤,
    重新獲取,
  } = useGetPostsQuery({ 頁數, 限制: 10 }); // 當你想在螢幕載入時取得資料時,使用 useQuery 鉤子。例如,在個人資料畫面上取得使用者個人資料。
  // 使用惰性查詢刷新直接取得第1頁
  const [triggerFetchFirstPage,{ 資料:lazyData }] = useLazyGetPostsQuery(); // useLazyquery 當你想要控制 api 呼叫時使用,例如按鈕點擊。

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

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

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

  const handleRefresh = async () =>; {
    設定刷新(真);
    設定頁面(1); // 將頁面重設為 1 以進行下一個捲動
    setPostsData([]); // 清除資料以避免重複

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

    如果(數據){
      設定貼文資料(資料); // 將貼文資料設定為第一頁的結果
    }

    設定刷新(假);
  };

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

  // 更新現有貼文並將「HASAN」新增至其標題中
  const handleUpdatePost = async (post) =>; {
    const { 資料:updatePost } = 等待 updatePost({
      id:帖子id,
      標題: `${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));
  };

  // 加載更多帖子以實現無限滾動
  const loadMorePosts = () =>; {
    if (!isFetching) {
      setPage((上一頁) => 上一頁 1);
    }
  };

  // 切換模態可見性
  consttoggleModal = () =>; {
    setModalVisible(!isModalVisible);
  };

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

  返回 (
    



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

概括:

您的 React Native 應用程式使用 Redux Toolkit (RTK) 查詢 來實現高效的資料管理和 API 互動。設定包括:

  1. 存儲配置:帶有redux-persist 的Redux 存儲,用於跨應用程序會話保存特定數據,用於錯誤日誌記錄的自定義中間件,以及用於在開發模式下進行偵錯的Reactotron。

  2. 有 RTK 查詢的 API:

    • authApi 透過登入突變處理驗證,將令牌儲存在 Redux 中。
    • postsApi 為貼文提供 CRUD 操作,在新增、更新或刪除貼文時使用快取標籤自動刷新資料。
    • usersApi 使用基於動態令牌的授權標頭取得使用者設定檔。
  3. Auth Slice:管理身分驗證令牌並提供在登入/登出時設定或清除令牌的操作。

  4. 應用程式和主應用程式元件

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

完整程式碼->

以上是透過 RTK 查詢在 React Native 中高效處理數據的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1317
25
PHP教程
1268
29
C# 教程
1246
24
JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript引擎:比較實施 JavaScript引擎:比較實施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

JavaScript:探索網絡語言的多功能性 JavaScript:探索網絡語言的多功能性 Apr 11, 2025 am 12:01 AM

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

如何使用Next.js(前端集成)構建多租戶SaaS應用程序 如何使用Next.js(前端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:22 AM

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

使用Next.js(後端集成)構建多租戶SaaS應用程序 使用Next.js(後端集成)構建多租戶SaaS應用程序 Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

從C/C到JavaScript:所有工作方式 從C/C到JavaScript:所有工作方式 Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript和Web:核心功能和用例 JavaScript和Web:核心功能和用例 Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

See all articles