DEV Community

Ramu Narasinga
Ramu Narasinga

Posted on • Originally published at thinkthroo.com

RTK query usage in Meshery codebase.

In this article, we review RTK query usage in Meshery codebase. We will look at:

  1. What is Meshery?

  2. What is RTK Query?

  3. RTK Query usage in Meshery.

I study patterns used in an open source project found on Github Trending. For this week, I reviewed some parts of Meshery codebase and wrote this article.

What is Meshery?

Meshery is the extensible Kubernetes manager. Meshery has 380+ Built-In integrations for your Cloud Native Infrastructure and Apps. Meshery seamlessly integrates with every CNCF project, your existing tools, multiple Clouds and Kubernetes clusters.

Learn more about https://meshery.io/

What is RTK Query?

RTK Query is a powerful data fetching and caching tool. It is designed to simplify common cases for loading data in a web application, eliminating the need to hand-write data fetching & caching logic yourself.

RTK Query is an optional addon included in the Redux Toolkit package, and its functionality is built on top of the other APIs in Redux Toolkit.

Basic usage

Create an API slice

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import type { Pokemon } from './types'

// Define a service using a base URL and expected endpoints
export const pokemonApi = createApi({
  reducerPath: 'pokemonApi',
  baseQuery: fetchBaseQuery({ baseUrl: 'https://pokeapi.co/api/v2/' }),
  endpoints: (build) => ({
    getPokemonByName: build.query<Pokemon, string>({
      query: (name) => `pokemon/${name}`,
    }),
  }),
})

// Export hooks for usage in functional components, which are
// auto-generated based on the defined endpoints
export const { useGetPokemonByNameQuery } = pokemonApi
Enter fullscreen mode Exit fullscreen mode

Configure the store

The “API slice” also contains an auto-generated Redux slice reducer and a custom middleware that manages subscription lifetimes. Both of those need to be added to the Redux store:

import { configureStore } from '@reduxjs/toolkit'
// Or from '@reduxjs/toolkit/query/react'
import { setupListeners } from '@reduxjs/toolkit/query'
import { pokemonApi } from './services/pokemon'

export const store = configureStore({
  reducer: {
    // Add the generated reducer as a specific top-level slice
    [pokemonApi.reducerPath]: pokemonApi.reducer,
  },
  // Adding the api middleware enables caching, invalidation, polling,
  // and other useful features of `rtk-query`.
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(pokemonApi.middleware),
})

// optional, but required for refetchOnFocus/refetchOnReconnect behaviors
// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization
setupListeners(store.dispatch)
Enter fullscreen mode Exit fullscreen mode

Use hooks in components

import * as React from 'react'
import { useGetPokemonByNameQuery } from './services/pokemon'

export default function App() {
  // Using a query hook automatically fetches data and returns query values
  const { data, error, isLoading } = useGetPokemonByNameQuery('bulbasaur')
  // Individual hooks are also accessible under the generated endpoints:
  // const { data, error, isLoading } = pokemonApi.endpoints.getPokemonByName.useQuery('bulbasaur')

  // render UI based on data and loading state
}
Enter fullscreen mode Exit fullscreen mode

Learn more about RTK Query.

RTK Query usage in Meshery.

In the above section, we learnt a simple RTK query usage example. Let’s see how Meshery has applied some of these concepts.

Create API Base:

You will find the below code at meshery/ui/rtk-query/index.js.

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const api = createApi({
  reducerPath: 'mesheryApi',
  baseQuery: fetchBaseQuery({ baseUrl: '/api/' }),
  endpoints: () => ({}),
});
Enter fullscreen mode Exit fullscreen mode

Please note that all the APIs related to RTK query are located in rtk-query folder.

Create API slices:

Below code snippet is picked from meshery/ui/rtk-query/user.js

import { ctxUrl } from '@/utils/multi-ctx';
import { api } from './index';
import { initiateQuery } from './utils';
import { useGetOrgsQuery } from './organization';
import { useGetWorkspacesQuery } from './workspace';

const Tags = {
  USER_PREF: 'userPref',
  LOAD_TEST_PREF: 'loadTestPref',
  PROVIDER_CAP: 'provider_capabilities',
};

export const userApi = api
  .enhanceEndpoints({
    addTagTypes: [Tags.USER_PREF, Tags.LOAD_TEST_PREF, Tags.PROVIDER_CAP],
  })
  .injectEndpoints({
    endpoints: (builder) => ({
      getLoadTestPrefs: builder.query({
        query: (selectedK8sContexts) => ({
        }),
        providesTags: [Tags.LOAD_TEST_PREF],
        // Transform response to directly get the loadTestPrefs
        transformResponse: (response) => response?.loadTestPrefs || {},
      }),

      updateLoadTestPrefs: builder.mutation({
        query: (queryArg) => ({
        }),
        invalidatesTags: [Tags.LOAD_TEST_PREF],
      }),
...
Enter fullscreen mode Exit fullscreen mode

Register the APIs in the store:

Below code is picked from meshery/ui/store/index.js

import eventsReducer from './slices/events';
import globalEnvironmentContextReducer from './slices/globalEnvironmentContext';
import { configureStore } from '@reduxjs/toolkit';
import { api } from '../rtk-query/index';
import mesheryUiReducer from './slices/mesheryUi';
import prefTestReducer from './slices/prefTest';
import telemetryReducer from './slices/telemetry';
import adapterReducer from './slices/adapter';
import { mesheryEventBus } from '@/utils/eventBus';

export const store = configureStore({
  reducer: {
    events: eventsReducer,
    globalEnvironmentContext: globalEnvironmentContextReducer,
    ui: mesheryUiReducer,
    prefTest: prefTestReducer,
    telemetry: telemetryReducer,
    adapter: adapterReducer,
    [api.reducerPath]: api.reducer,
  },
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(api.middleware),
});

mesheryEventBus.on('DISPATCH_TO_MESHERY_STORE').subscribe((event) => {
  console.log('Dispatching to Meshery Store:', event.data);
  store.dispatch(event.data);
});
Enter fullscreen mode Exit fullscreen mode

About me:

Hey, my name is Ramu Narasinga. I study codebase architecture in large open-source projects.

Email: ramu.narasinga@gmail.com

Want to learn from open-source? Solve challenges inspired by open-source projects.

References:

  1. https://meshery.io/

  2. https://redux-toolkit.js.org/rtk-query/overview

  3. https://github.com/meshery/meshery/blob/master/ui/rtk-query/index.js

  4. https://github.com/meshery/meshery/tree/master/ui/rtk-query

  5. https://github.com/meshery/meshery/blob/master/ui/rtk-query/user.js

  6. https://github.com/meshery/meshery/blob/b7982fb436da7a3c466afd1bb2eb5104c347e95a/ui/store/index.js#L12

Top comments (0)