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

ホームページ ウェブフロントエンド jsチュートリアル RTK クエリを使用した React Native での効率的なデータ処理

RTK クエリを使用した React Native での効率的なデータ処理

Nov 30, 2024 am 10:01 AM

このガイドでは以下について説明します:

  • CRUD オペレーション
  • ページネーション
  • RTK クエリを使用した Redux 永続化
  • 複數(shù)のベース URL の使用
  • 保護(hù)された公共ルート
  • キャッシュの管理と無効化

Efficient Data Handling in React Native with RTK Query

RTK Query は、Redux Toolkit (RTK) に組み込まれた高度なデータフェッチおよびキャッシュ ツールです。データのフェッチ、キャッシュ、更新などの一般的なタスク用の Redux スライスとフックを生成することで、API の対話を合理化します。主な機(jī)能は次のとおりです:

  1. 自動(dòng)キャッシュ: RTK クエリはデータをキャッシュし、データが無効になったときに自動(dòng)的に再取得して、UI に常に最新のデータが含まれるようにします。
  2. キャッシュの無効化: タグを使用すると、RTK クエリで特定のデータをいつ再フェッチするかを定義できます。これにより、データを手動(dòng)で更新することなく、キャッシュを最新の狀態(tài)に保つことができます。
  3. 自動(dòng)生成フック: RTK クエリは各 API エンドポイントのフックを作成し、単純な React フック (useGetPostsQuery、useCreatePostMutation など) を使用して API を呼び出すことができます。
  4. エラー処理: ミドルウェアによるカスタム エラー処理が含まれており、エラーの捕捉と表示が簡(jiǎn)単になります。
  5. 簡(jiǎn)素化された Redux 統(tǒng)合: RTK クエリは Redux と直接統(tǒng)合されるため、グローバルな狀態(tài)管理やキャッシュに追加のライブラリは必要ありません。

RTK クエリと React クエリの比較

React QueryRTK Query はどちらも、React アプリケーションでのデータのフェッチとキャッシュのソリューションを提供しますが、長(zhǎng)所とユースケースが異なります。

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 クエリの選択:

  • 次の場(chǎng)合に RTK クエリを使用します:

    • あなたはすでに Redux を使用していて、データ取得のための統(tǒng)合された合理化されたソリューションを必要としています。
    • Redux 內(nèi)で集中エラー処理と devtools を統(tǒng)合する必要があります。
  • 次の場(chǎng)合に React Query を使用します:

    • Redux に依存しない、より軽量なセットアップが必要です。
    • 個(gè)別のサーバー狀態(tài)管理を好み、グローバルなアプリ?duì)顟B(tài)は必要ありません。

本質(zhì)的に、RTK Query は Redux 中心のアプリケーションに優(yōu)れていますが、React Query は Redux を使用しないプロジェクトや、よりローカライズされたサーバー狀態(tài)管理に焦點(diǎn)を當(dāng)てたプロジェクトに柔軟性とシンプルさを提供します。


Efficient Data Handling in React Native with RTK Query



1. ストアの構(gòu)成とセットアップ

// 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 ストア (src/store/store.js): Redux ストアは、アプリケーションの狀態(tài)を保持する主要な構(gòu)造です。セットアップでは、Redux 狀態(tài)の特定の部分をローカルに保存する redux-persist によって拡張され、アプリが再起動(dòng)しても保持されます。

  • redux-persist:

    • 目的: Redux 狀態(tài)の一部をアプリセッション間で永続的に維持するのに役立ちます。
    • 構(gòu)成:persistConfig オブジェクトは、auth、postApi、および usersApi を永続化 (ブラックリストに登録) しないように指定します。つまり、アプリの再起動(dòng)時(shí)にデータがリセットされます。
    • persistReducer は、Reducer 構(gòu)成と永続化機(jī)能を組み合わせたものです。
  • エンハンサー: カスタム エンハンサーは、開発モードで Reactotron を統(tǒng)合するために使用されます。これは、Redux アクション、狀態(tài)、およびネットワーク リクエストをデバッグするための便利なツールです。これは開発時(shí)のみ有効となり、運(yùn)用環(huán)境に影響を與えることなくデバッグが容易になります。

  • ミドルウェア:

    • RTK クエリ ミドルウェア (postsApi.middleware、usersApi.middleware、authApi.middleware) には、自動(dòng)キャッシュ管理の機(jī)能が追加され、データのフェッチが効率化されます。
    • rtkQueryErrorLogger: カスタム ミドルウェアは、API 呼び出しが失敗したときにエラーをログに記録します。 RTK クエリの isRejectedWithValue 関數(shù)を使用してエラーをキャッチして処理し、ユーザーに問題について警告したり、他のアクションを?qū)g行したりできるようにします。
  • setupListeners: この関數(shù)は、アプリがフォーカスを取り戻したときやバックグラウンドから再開したときなど、特定のイベントが発生したときにデータを自動(dòng)的に再取得できるようにし、手動(dòng)で更新せずに新しいデータをユーザーに提供します。



2. RTK クエリを使用した API 定義

RTK クエリは、Redux スライス、フック、キャッシュを自動(dòng)生成することで API 呼び出しを簡(jiǎn)素化します。定義した API の內(nèi)訳は次のとおりです:

// 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):
    • 認(rèn)証のためにユーザーの資格情報(bào) (ユーザー名、パスワードなど) をサーバーに送信するログインの変更を定義します。
    • onQueryStarted: ログインが成功すると、setToken アクションを使用して、返されたトークンを Redux に保存します。これにより、他のエンドポイントへの安全な認(rèn)証されたリクエストが可能になります。

// 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 には、投稿を操作する (取得、作成、更新、削除) ための複數(shù)のエンドポイントが含まれています。
      • getPosts: ページ分割された投稿を取得します。つまり、データをより小さなチャンク (ページ) で取得し、パフォーマンスと読み込み時(shí)間を向上させます。
      • createPost、updatePost、および deletePost: これらはそれぞれ、異なるアクション (投稿の作成、更新、または削除) を?qū)g行します。
    • キャッシュ用のタグ: 各エンドポイントはタグを使用します (例: { type: 'Posts', id }) キャッシュの無効化と更新を自動(dòng)的に管理します。たとえば、投稿を作成または削除するとキャッシュが無効になり、getPosts は手動(dòng)介入なしで新しいデータを取得するように求められます。

// 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 は、認(rèn)証されたユーザーのプロファイルを取得し、Redux からのトークンに基づいて Authorization ヘッダーを設(shè)定します。
    • Headers: prepareHeaders は、利用可能な場(chǎng)合はすべてのリクエストにトークンを動(dòng)的に添付し、安全で承認(rèn)された API リクエストを許可します。


3. 認(rèn)証スライス (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) (この場(chǎng)合はユーザー認(rèn)証) を管理します。
  • 狀態(tài)管理: authSlice は、保護(hù)された API エンドポイントにアクセスするために使用されるユーザーのトークンを保持します。
  • アクション:
    • setToken: 認(rèn)証トークンを Redux 狀態(tài)に保存します。
    • 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 の狀態(tài)変更の追跡、API リクエストの監(jiān)視、ログの検査に役立つデバッグ ツールです。
  • Setup: console.log 出力と Redux アクションをキャプチャするように設(shè)定されています。開発モードでは、このセットアップは、追加のコードを追加したり、運(yùn)用パフォーマンスを変更したりすることなく、デバッグするための強(qiáng)力な方法を提供します。


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 (永続化された狀態(tài)が取得されるまでレンダリングを遅らせるため) でラップします。
    • PersistGate は、アプリが表示される前に永続化されたデータを確実にロードし、ロード時(shí)間の不一致を削減します。

// src/MainApp.js
import React, { useEffect, useState } from 'react';
輸入 {
  アクティビティインジケーター、
  ボタン、
  フラットリスト、
  モーダル、
  リフレッシュコントロール、
  スタイルシート、
  文章、
  テキスト入力、
  ビュー、
「反応ネイティブ」から;
import { SafeAreaView } から 'react-native-safe-area-context';
import { useDispatch, useSelector } から 'react-redux';
import { useLoginMutation } から './api/authApi';
輸入 {
  useCreatePostMutation、
  useDeletePostMutation、
  useGetPostsQuery、
  useLazyGetPostsQuery、
  UpdatePostMutation を使用する、
'./api/postsApi' から;
import { useGetUserProfileQuery } から './api/usersApi';
インポート { ログアウト }'./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();

  // トークンが利用可能な場(chǎng)合にユーザー プロファイルを取得します
  const { データ: userProfile, refetch: refetchUserProfile } = useGetUserProfileQuery(未定義, {
    スキップ: !トークン、
  });

  // ページ分割された投稿を取得します
  定數(shù){
    データ: 投稿、
    読み込み中、
    フェッチ中、
    エラーです、
    再フェッチ、
  } = useGetPostsQuery({ ページ、制限: 10 }); // useQuery フックは、畫面ロード時(shí)にデータをフェッチする場(chǎng)合に使用されます。たとえば、プロフィール畫面でユーザープロフィールを取得します。
  // 更新用の遅延クエリを使用して、ページ 1 を直接フェッチします
  const [triggerFetchFirstPage, { data: LazyData }] = useLazyGetPostsQuery(); // useLazyquery は、ボタンのクリック時(shí)など、API 呼び出しを制御する場(chǎng)合に使用されます。

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

  useEffect(() => {
    if (投稿) {
      setPostsData((prevData) => (ページ === 1 ? 投稿 : [...prevData, ...posts]));
    }
  }, [投稿、ページ]);

  // ログインハンドラ
  const handleLogin = async () => {
    試す {
      const credentials = { ユーザー名: 'emilys'、パスワード: 'emilyspass' };
      ログインを待ちます(認(rèn)証情報(bào));
      console.log('ユーザープロファイル', ユーザープロファイル);
      refetchUserProfile();
    } キャッチ (エラー) {
      console.error('ログインに失敗しました:', エラー);
    }
  };

  const handleRefresh = async () => {
    setRefreshing(true);
    setPage(1); // 次のスクロールのためにページを 1 にリセットします
    setPostsData([]); // 重複を避けるためにデータをクリアします

    // 最初のページのフェッチを明示的にトリガーします
    const { data } = awaittriggerFetchFirstPage({ ページ: 1, 制限: 10 });

    if (データ) {
      setPostsData(データ); // 投稿データを最初のページの結(jié)果に設(shè)定します
    }

    setRefreshing(false);
  };

  // 新しい投稿を作成して先頭に追加し、リストを再取得します
  const handleCreatePost = async () => {
    if (newPostTitle) {
      const { data: newPost } = await createPost({ title: newPostTitle, body: '新規(guī)投稿コンテンツ' });
      setNewPostTitle('');
      setPostsData((prevData) => [newPost, ...prevData]);
      再フェッチ();
    }
  };

  // 既存の投稿を更新し、タイトルに「HASAN」を追加します
  const handleUpdatePost = async (post) => {
    const { データ: updatedPost } = updatePostを待ちます({
      id: post.id、
      タイトル: `${post.title} ハサン`,
    });
    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));
  };

  // 無限スクロールのためにさらに投稿を読み込みます
  constloadMorePosts = () => {
    if (!isFetching) {
      setPage((前のページ) => 前のページ 1);
    }
  };

  // モーダルの可視性を切り替えます
  const toggleModal = () => {
    setModalVisible(!isModalVisible);
  };

  if (isLoading && page === 1) return <Text>Loading...</Text>;
  if (isError) return <Text>投稿の取得中にエラーが発生しました。</Text>;

  戻る (
    



  • MainApp コンポーネント (src/MainApp.js):
    • 狀態(tài)とフック: ローカル狀態(tài) (投稿のページネーションなど) と、特定のイベントでアクションをトリガーする useLoginMutation などのフックを管理します。
    • ログイン:
      • useLoginMutation を使用してユーザーをログインさせ、refetchUserProfile をトリガーしてユーザー プロファイル データをロードします。
      • 條件付きクエリ: 有効なトークンが存在する場(chǎng)合にのみユーザー プロファイルを取得し (スキップ: !token)、不要な API 呼び出しを減らします。
    • 投稿を取得しています:
      • useGetPostsQuery を使用してページ分割された投稿を取得し、ユーザーがスクロールするにつれてより多くのデータを取得することで無限スクロールをサポートします。
      • 更新コントロール: ユーザーが投稿リストを更新できるようにします。これは、モバイルでのプルツーリフレッシュ機(jī)能に役立ちます。
    • 投稿の作成、更新、削除:
      • Create: createPost を呼び出し、新しい投稿を先頭にして投稿リストを即座に更新します。
      • 更新: 更新時(shí)に投稿のタイトルに「HASAN」を追加します。
      • 削除: deletePost によるキャッシュの無効化により、ページをリロードすることなく投稿を削除し、UI を更新します。
    • UI 要素:
      • モーダルにはユーザー プロフィールが表示されます。プロフィール ボタンは、userProfile データがロードされている場(chǎng)合にのみ表示され、ユーザー エクスペリエンスが向上します。
    • FlatList: スクロール可能なページ分割された形式で投稿を表示し、使いやすさを高めます。

まとめ:

React Native アプリは、効率的なデータ管理と API 対話のために Redux Toolkit (RTK) Query を使用します。セットアップには以下が含まれます:

  1. ストア構(gòu)成: アプリセッション間で特定のデータを保存する redux-persist を備えた Redux ストア、エラーログ用のカスタムミドルウェア、開発モードでのデバッグ用の Reactotron。

  2. RTK クエリを使用した API:

    • authApi は、ログインの変更による認(rèn)証を処理し、トークンを Redux に保存します。
    • postsApi は、投稿の CRUD 操作を提供し、投稿の追加、更新、または削除時(shí)にキャッシュ タグを使用してデータを自動(dòng)的に更新します。
    • usersApi は、動(dòng)的なトークンベースの認(rèn)証ヘッダーを含むユーザー プロファイルを取得します。
  3. 認(rèn)証スライス: 認(rèn)証トークンを管理し、ログイン/ログアウト時(shí)にトークンを設(shè)定またはクリアするためのアクションを提供します。

  4. アプリと MainApp コンポーネント:

    • メイン アプリは Provider と PersistGate でコンポーネントをラップし、レンダリング前に狀態(tài)が確実に読み込まれるようにします。
    • MainApp は、投稿の取得、作成、更新、削除を管理します。條件付きでデータを読み込み (例: トークンが存在する場(chǎng)合にのみユーザー プロフィールを取得)、ページネーションと無限スクロールをサポートします
    • ページ分割された投稿リストには FlatList、プロフィールにはモーダル、すっきりと整理されたレイアウトには基本スタイルを使用します。

完全なコード->

以上がRTK クエリを使用した React Native での効率的なデータ処理の詳細(xì)內(nèi)容です。詳細(xì)については、PHP 中國(guó)語 Web サイトの他の関連記事を參照してください。

このウェブサイトの聲明
この記事の內(nèi)容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰屬します。このサイトは、それに相當(dāng)する法的責(zé)任を負(fù)いません。盜作または侵害の疑いのあるコンテンツを見つけた場(chǎng)合は、admin@php.cn までご連絡(luò)ください。

ホットAIツール

Undress AI Tool

Undress AI Tool

脫衣畫像を無料で

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

寫真から衣服を削除するオンライン AI ツール。

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡(jiǎn)単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中國(guó)語版

SublimeText3 中國(guó)語版

中國(guó)語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強(qiáng)力な PHP 統(tǒng)合開発環(huán)境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Java vs. JavaScript:混亂を解消します Java vs. JavaScript:混亂を解消します Jun 20, 2025 am 12:27 AM

JavaとJavaScriptは異なるプログラミング言語であり、それぞれ異なるアプリケーションシナリオに適しています。 Javaは大規(guī)模なエンタープライズおよびモバイルアプリケーション開発に使用されますが、JavaScriptは主にWebページ開発に使用されます。

JavaScriptコメント:短い説明 JavaScriptコメント:短い説明 Jun 19, 2025 am 12:40 AM

JavaScriptcommentsEareEssentialential-formaining、およびGuidingCodeexecution.1)single-linecommentseared forquickexplanations.2)多LinecommentsexplaincomplexlogiCorprovidededocumentation.3)clarifyspartsofcode.bestpractic

JSで日付と時(shí)間を操作する方法は? JSで日付と時(shí)間を操作する方法は? Jul 01, 2025 am 01:27 AM

JavaScriptで日付と時(shí)間を処理する場(chǎng)合は、次の點(diǎn)に注意する必要があります。1。日付オブジェクトを作成するには多くの方法があります。 ISO形式の文字列を使用して、互換性を確保することをお?jiǎng)幛幛筏蓼埂?2。時(shí)間情報(bào)を取得および設(shè)定して、メソッドを設(shè)定でき、月は0から始まることに注意してください。 3.手動(dòng)でのフォーマット日付には文字列が必要であり、サードパーティライブラリも使用できます。 4.ルクソンなどのタイムゾーンをサポートするライブラリを使用することをお?jiǎng)幛幛筏蓼?。これらの重要なポイントを?xí)得すると、一般的な間違いを効果的に回避できます。

なぜの下部にタグを配置する必要があるのですか? なぜの下部にタグを配置する必要があるのですか? Jul 02, 2025 am 01:22 AM

PLACSTHETTHETTHE BOTTOMOFABLOGPOSTORWEBPAGESERVESPAGESPORCICALPURPOSESESFORSEO、userexperience、andDesign.1.IthelpswithiobyAllowingseNStoAccessKeysword-relevanttagwithtagwithtagwithtagwithemaincontent.2.iTimrovesexperiencebyepingepintepepinedeeping

JavaScript vs. Java:開発者向けの包括的な比較 JavaScript vs. Java:開発者向けの包括的な比較 Jun 20, 2025 am 12:21 AM

javascriptispreferredforwebdevelopment、whilejavaisbetterforlge-scalebackendsystemsandroidapps.1)javascriptexcelsininintingtivewebexperiences withitsdynAmicnature anddommanipulation.2)javaofferstruntypyping-dobject-reientedpeatures

JavaScript:効率的なコーディングのためのデータ型の調(diào)査 JavaScript:効率的なコーディングのためのデータ型の調(diào)査 Jun 20, 2025 am 12:46 AM

javascripthassevenfundamentaldatypes:number、string、boolean、undefined、null、object、andsymbol.1)numberseadouble-precisionformat、有用であるため、有用性の高いものであるため、but-for-loating-pointarithmetic.2)ストリングリムムット、使用率が有用であること

DOMでのイベントの泡立ちとキャプチャとは何ですか? DOMでのイベントの泡立ちとキャプチャとは何ですか? Jul 02, 2025 am 01:19 AM

イベントキャプチャとバブルは、DOMのイベント伝播の2つの段階です。キャプチャは最上層からターゲット要素までであり、バブルはターゲット要素から上層までです。 1.イベントキャプチャは、AddEventListenerのUseCaptureパラメーターをTrueに設(shè)定することにより実裝されます。 2。イベントバブルはデフォルトの動(dòng)作であり、UseCaptureはfalseに設(shè)定されているか、省略されます。 3。イベントの伝播を使用して、イベントの伝播を防ぐことができます。 4.イベントバブルは、動(dòng)的なコンテンツ処理効率を改善するためにイベント委任をサポートします。 5.キャプチャを使用して、ロギングやエラー処理など、事前にイベントを傍受できます。これらの2つのフェーズを理解することは、タイミングとJavaScriptがユーザー操作にどのように反応するかを正確に制御するのに役立ちます。

JavaとJavaScriptの違いは何ですか? JavaとJavaScriptの違いは何ですか? Jun 17, 2025 am 09:17 AM

JavaとJavaScriptは、異なるプログラミング言語です。 1.Javaは、エンタープライズアプリケーションや大規(guī)模なシステムに適した、靜的に型付けされ、コンパイルされた言語です。 2。JavaScriptは動(dòng)的なタイプと解釈された言語であり、主にWebインタラクションとフロントエンド開発に使用されます。

See all articles