首页 >web前端 >js教程 >通过 RTK 查询在 React Native 中高效处理数据

通过 RTK 查询在 React Native 中高效处理数据

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-11-30 10:01:14950浏览

在本指南中,我们将介绍:

  • 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