Home > Web Front-end > JS Tutorial > Complete redux toolkit (Part - 4)

Complete redux toolkit (Part - 4)

PHPz
Release: 2024-09-11 14:32:39
Original
960 people have browsed it

Complete redux toolkit (Part - 4)

Part 4: Advanced Topics in RTK Query.

This part will focus on advanced features and use cases in RTK Query, including customising queries, handling authentication, optimistic updates, and performance optimisation.

Part 4: Advanced Topics in RTK Query

1. Introduction to Advanced RTK Query Concepts

In the previous part, we covered the basics of using RTK Query for fetching and mutating data. Now, we will dive into more advanced features that make RTK Query even more powerful. These features allow you to customize queries, manage authentication, optimize performance, and handle optimistic updates for a smoother user experience.

2. Customizing baseQuery for Authentication

When working with APIs that require authentication, you need to customize the baseQuery to include authentication headers like JWT tokens or API keys.

Step 1: Create a Custom baseQuery

You can create a custom baseQuery function that adds authorization headers to every request.

// src/app/customBaseQuery.js
import { fetchBaseQuery } from '@reduxjs/toolkit/query/react';

const customBaseQuery = fetchBaseQuery({
  baseUrl: 'https://jsonplaceholder.typicode.com/',
  prepareHeaders: (headers, { getState }) => {
    const token = getState().auth.token; // Assuming auth slice has token
    if (token) {
      headers.set('Authorization', `Bearer ${token}`);
    }
    return headers;
  },
});

export default customBaseQuery;
Copy after login

Explanation:

  • prepareHeaders: This function allows you to customize headers for each request. It retrieves the token from the Redux store and attaches it to the Authorization header.

Step 2: Use the Custom baseQuery in createApi

Modify your postsApi.js file to use the custom baseQuery:

// src/features/posts/postsApi.js
import { createApi } from '@reduxjs/toolkit/query/react';
import customBaseQuery from '../../app/customBaseQuery';

export const postsApi = createApi({
  reducerPath: 'postsApi',
  baseQuery: customBaseQuery, // Use the custom base query here
  tagTypes: ['Post'],
  endpoints: (builder) => ({
    fetchPosts: builder.query({
      query: () => 'posts',
      providesTags: (result) =>
        result ? result.map(({ id }) => ({ type: 'Post', id })) : ['Post'],
    }),
    addPost: builder.mutation({
      query: (newPost) => ({
        url: 'posts',
        method: 'POST',
        body: newPost,
      }),
      invalidatesTags: ['Post'],
    }),
  }),
});

export const { useFetchPostsQuery, useAddPostMutation } = postsApi;
Copy after login

3. Optimistic Updates with RTK Query

Optimistic updates allow you to immediately update the UI before the server confirms the mutation, providing a smoother user experience. If the server returns an error, the UI can revert to the previous state.

Step 1: Implement Optimistic Updates in Mutations

You can implement optimistic updates using the onQueryStarted lifecycle method provided by RTK Query.

// src/features/posts/postsApi.js
addPost: builder.mutation({
  query: (newPost) => ({
    url: 'posts',
    method: 'POST',
    body: newPost,
  }),
  invalidatesTags: ['Post'],
  onQueryStarted: async (newPost, { dispatch, queryFulfilled }) => {
    // Optimistic update: immediately add the new post to the cache
    const patchResult = dispatch(
      postsApi.util.updateQueryData('fetchPosts', undefined, (draftPosts) => {
        draftPosts.push({ id: Date.now(), ...newPost }); // Fake ID for optimistic update
      })
    );
    try {
      await queryFulfilled; // Await server response
    } catch {
      patchResult.undo(); // Revert if the mutation fails
    }
  },
}),
Copy after login

Explanation:

  • onQueryStarted: This lifecycle method is triggered when a mutation starts. It provides dispatch and queryFulfilled parameters to manage cache updates.
  • postsApi.util.updateQueryData: This utility function allows you to optimistically update cached data.
  • patchResult.undo(): Reverts the optimistic update if the server returns an error.

4. Handling Dependent Queries

Sometimes, you may need to perform dependent queries, where one query depends on the result of another. RTK Query provides the skip parameter to control when a query is executed.

Example: Fetch Post Details Based on Selected Post ID

// src/features/posts/PostDetails.js
import React from 'react';
import { useFetchPostQuery } from './postsApi';

const PostDetails = ({ postId }) => {
  const { data: post, error, isLoading } = useFetchPostQuery(postId, { skip: !postId });

  if (!postId) return <p>Select a post to view details.</p>;
  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error loading post details.</p>;

  return (
    <div>
      <h3>{post.title}</h3>
      <p>{post.body}</p>
    </div>
  );
};

export default PostDetails;
Copy after login

Explanation:

  • useFetchPostQuery: A query hook that takes postId as an argument. If postId is not provided, the query is skipped using { skip: !postId }.

5. Polling and Real-Time Data with RTK Query

RTK Query supports polling to keep data fresh at a specified interval. This is useful for real-time data synchronization.

Step 1: Use Polling in Queries

You can enable polling for any query using the pollingInterval option.

// src/features/posts/PostsList.js
import React from 'react';
import { useFetchPostsQuery } from './postsApi';

const PostsList = () => {
  const { data: posts, error, isLoading } = useFetchPostsQuery(undefined, {
    pollingInterval: 30000, // Poll every 30 seconds
  });

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>An error occurred: {error.message}</p>;

  return (
    <section>
      <h2>Posts</h2>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </section>
  );
};

export default PostsList;
Copy after login

Explanation:

  • pollingInterval: This option specifies the interval (in milliseconds) at which the query should poll the server for new data.

6. Optimizing Performance with selectFromResult

RTK Query provides the selectFromResult option for advanced performance optimizations by allowing you to select specific data from the query result.

Step 1: Using selectFromResult to Optimize Re-Renders

The selectFromResult option can be used to prevent unnecessary re-renders when only a subset of the query result is needed.

// src/features/posts/PostTitleList.js
import React from 'react';
import { useFetchPostsQuery } from './postsApi';

const PostTitleList = () => {
  const { data: posts } = useFetchPostsQuery(undefined, {
    selectFromResult: ({ data }) => ({ titles: data?.map((post) => post.title) }),
  });

  return (
    <section>
      <h2>Post Titles</h2>
      <ul>
        {posts?.map((title, index) => (
          <li key={index}>{title}</li>
        ))}
      </ul>
    </section>
  );
};

export default PostTitleList;
Copy after login

Explanation:

  • selectFromResult: This option allows you to select only the titles from the fetched posts, preventing unnecessary re-renders when other data in the query result changes.

7. Conclusion and Next Steps

In this part, we explored advanced topics in RTK Query, such as customizing baseQuery for authentication, handling optimistic updates, managing dependent queries, using polling for real-time data synchronization, and optimizing performance with selectFromResult. RTK Query's rich feature set makes it a powerful tool for handling data fetching and caching in modern Redux applications.

In the next part, we'll discuss Testing Strategies for Redux Toolkit and RTK Query, covering unit testing, integration testing, and best practices for ensuring robust and maintainable code.

Stay tuned for Part 5: Testing Strategies for Redux Toolkit and RTK Query!

The above is the detailed content of Complete redux toolkit (Part - 4). For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template