Skip to content

Instantly share code, notes, and snippets.

@ronnaf
Last active February 7, 2024 10:52
Show Gist options
  • Save ronnaf/b89f7208d01af84c67d7a5425b376d14 to your computer and use it in GitHub Desktop.
Save ronnaf/b89f7208d01af84c67d7a5425b376d14 to your computer and use it in GitHub Desktop.
{
"rtk query service crud with automatic cache updates": {
"prefix": "rtkqservauto",
"body": [
"import type { EntityState } from '@reduxjs/toolkit';",
"import { TypedUseQueryStateResult } from '@reduxjs/toolkit/dist/query/react/buildHooks';",
"",
"import { apiService } from '../';",
"import { ${2:${TM_DIRECTORY/^.+\\/(.*)$/${1:/camelcase}/}}ApiConfigs, ${3:${TM_DIRECTORY/^.+\\/(.*)$/${1:/pascalcase}/}}sConfigParams } from './configs';",
"",
"export const $2Service = apiService.injectEndpoints({",
" endpoints: (build) => ({",
" get$3s: build.query<$3sGetAllApiResponse, $3sGetAllApiArg>({",
" query: $2ApiConfigs.get$3s,",
" providesTags: (result) =>",
" result",
" ? [",
" { type: '$3', id: 'LIST' },",
" ...result.items.map(($2) => ({ type: '$3' as const, id: $2.id })),",
" ]",
" : [{ type: '$3', id: 'LIST' }],",
" }),",
" create$3: build.mutation<$3sCreateApiResponse, $3sCreateApiArg>({",
" query: $2ApiConfigs.create$3,",
" invalidatesTags: [{ type: '$3', id: 'LIST' }],",
" }),",
" delete$3: build.mutation<$3sDeleteApiResponse, $3sDeleteApiArg>({",
" query: $2ApiConfigs.delete$3,",
" invalidatesTags: [{ type: '$3', id: 'LIST' }],",
" }),",
" update$3: build.mutation<$3sUpdateApiResponse, $3sUpdateApiArg>({",
" query: $2ApiConfigs.update$3,",
" invalidatesTags: (result, error, arg) => [{ type: '$3', id: arg.id }],",
" }),",
" }),",
" overrideExisting: true,",
"});",
"",
"export const {",
" useGet$3sQuery,",
" useLazyGet$3sQuery,",
" useCreate$3Mutation,",
" useDelete$3Mutation,",
" useUpdate$3Mutation,",
"} = $2Service;"
"",
"// Get all",
"export type $3sGetAllBaseQueryReturn = IPaginatedResult<unknown>;",
"export type $3sGetAllApiResponse = EntityState<unknown>;",
"export type $3sGetAllApiArg = $3sConfigParams<'get$3s'>;",
"export type $3sGetAllQueryResult = TypedUseQueryStateResult<$3sGetAllApiResponse, unknown, any>;",
"// Create",
"export type $3sCreateApiResponse = unknown;",
"export type $3sCreateApiArg = $3sConfigParams<'create$3'>;",
"// Delete",
"export type $3sDeleteApiResponse = string;",
"export type $3sDeleteApiArg = $3sConfigParams<'delete$3'>;",
"// Update",
"export type $3sUpdateApiResponse = unknown;",
"export type $3sUpdateApiArg = $3sConfigParams<'update$3'>;",
""
],
"description": "rtk query service"
},
"rtk query service crud with manual cache updates": {
"prefix": "rtkqservmanual",
"body": [
"import type { EntityState } from '@reduxjs/toolkit';",
"import { createEntityAdapter } from '@reduxjs/toolkit';",
"import { TypedUseQueryStateResult } from '@reduxjs/toolkit/dist/query/react/buildHooks';",
"",
"import { apiService } from '../';",
"import { ${2:${TM_DIRECTORY/^.+\\/(.*)$/${1:/camelcase}/}}ApiConfigs, ${3:${TM_DIRECTORY/^.+\\/(.*)$/${1:/pascalcase}/}}sConfigParams } from './configs';",
"",
"export const $2Adapter = createEntityAdapter<unknown>();",
"",
"export const $2InitialState = $2Adapter.getInitialState();",
"",
"export const $2Service = apiService.injectEndpoints({",
" endpoints: (build) => ({",
" get$3s: build.query<$3sGetAllApiResponse, $3sGetAllApiArg>({",
" query: $2ApiConfigs.get$3s,",
" transformResponse(baseQueryReturnValue: $3sGetAllBaseQueryReturn) {",
" return $2Adapter.setAll($2InitialState, baseQueryReturnValue.items);",
" },",
" }),",
" create$3: build.mutation<$3sCreateApiResponse, $3sCreateApiArg>({",
" query: $2ApiConfigs.create$3,",
" async onQueryStarted(_, { dispatch, queryFulfilled }) {",
" try {",
" const { data } = await queryFulfilled;",
" dispatch(",
" $2Service.util.updateQueryData('get$3s', undefined, (draft) => {",
" $2Adapter.addOne(draft, data);",
" })",
" );",
" // Other side effects?",
" // Although it's better to include the side effects in the component this is being used on to maximize reusability",
" } catch (error) {",
" // Other side effects?",
" } finally {",
" // Other side effects?",
" }",
" },",
" }),",
" delete$3: build.mutation<$3sDeleteApiResponse, $3sDeleteApiArg>({",
" query: $2ApiConfigs.delete$3,",
" async onQueryStarted({ id }, { dispatch, queryFulfilled }) {",
" try {",
" await queryFulfilled;",
" dispatch(",
" $2Service.util.updateQueryData('get$3s', undefined, (draft) => {",
" $2Adapter.removeOne(draft, id);",
" })",
" );",
" } finally {",
" }",
" },",
" }),",
" update$3: build.mutation<$3sUpdateApiResponse, $3sUpdateApiArg>({",
" query: $2ApiConfigs.update$3,",
" async onQueryStarted({ id }, { dispatch, queryFulfilled }) {",
" try {",
" const { data } = await queryFulfilled;",
" dispatch(",
" $2Service.util.updateQueryData('get$3s', undefined, (draft) => {",
" $2Adapter.updateOne(draft, { id: id, changes: data });",
" })",
" );",
" } catch (error) {",
" } finally {",
" }",
" },",
" }),",
" }),",
" overrideExisting: true,",
"});",
"",
"export const {",
" useGet$3sQuery,",
" useLazyGet$3sQuery,",
" useCreate$3Mutation,",
" useDelete$3Mutation,",
" useUpdate$3Mutation,",
"} = $2Service;"
"",
"// Get all",
"export type $3sGetAllBaseQueryReturn = IPaginatedResult<unknown>;",
"export type $3sGetAllApiResponse = EntityState<unknown>;",
"export type $3sGetAllApiArg = $3sConfigParams<'get$3s'>;",
"export type $3sGetAllQueryResult = TypedUseQueryStateResult<$3sGetAllApiResponse, unknown, any>;",
"// Create",
"export type $3sCreateApiResponse = unknown;",
"export type $3sCreateApiArg = $3sConfigParams<'create$3'>;",
"// Delete",
"export type $3sDeleteApiResponse = string;",
"export type $3sDeleteApiArg = $3sConfigParams<'delete$3'>;",
"// Update",
"export type $3sUpdateApiResponse = unknown;",
"export type $3sUpdateApiArg = $3sConfigParams<'update$3'>;",
""
],
"description": "rtk query service"
},
"rtk query configs": {
"prefix": "rtkqconfig",
"body": [
"import { ApiRequestConfig } from '../types';",
"",
"/**",
" * Exported interface that represents various endpoints related to this domain (${2:${TM_DIRECTORY/^.+\\\\/(.*)$/${1:/camelcase}/}})",
" * Each endpoint adheres to type helper ApiRequestConfig",
" */",
"export interface ${3:${TM_DIRECTORY/^.+\\\\/(.*)$/${1:/pascalcase}/}}sApiConfigs {",
" get$3s: ApiRequestConfig;",
" create$3: ApiRequestConfig<{ dto: unknown }>;",
" delete$3: ApiRequestConfig<{ id: string }>;",
" update$3: ApiRequestConfig<{ id: string; dto: unknown }>;",
"}",
"",
"/**",
" * A utility type to easily access config parameters of the this domain ($2)",
" *",
" * @example",
" * ```",
" * type Create$3Args = $3sConfigParams<'create$3'>",
" *",
" * const args: Create$3Args = {...}",
" * console.log(args.dto)",
" * ```",
" */",
"export type $3sConfigParams<Config extends keyof $3sApiConfigs> = Parameters<",
" $3sApiConfigs[Config]",
">[0];",
"",
"/**",
" * The exported API config object that specifies how to make API requests",
" */",
"export const $2ApiConfigs: $3sApiConfigs = {",
" get$3s: () => ({",
" method: 'GET',",
" uri: '$2',",
" }),",
" create$3: ({ dto }) => ({",
" method: 'POST',",
" uri: '$2',",
" data: dto,",
" }),",
" delete$3: ({ id }) => ({",
" method: 'DELETE',",
" uri: `$2/${id}`,",
" }),",
" update$3: ({ id, dto }) => ({",
" method: 'PUT',",
" uri: `$2/${id}`,",
" data: dto,",
" }),",
"};",
""
],
"description": "rtk query configs"
},
"rtk slice": {
"prefix": "rtkslice",
"body": [
"import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';",
"",
"export const ${2:${TM_DIRECTORY/^.+\\\\/(.*)$/${1:/camelcase}/}}sAdapter = createEntityAdapter<${3:unknown}>();",
"",
"export const $2sInitialState = $2sAdapter.getInitialState();",
"",
"export const $2sSlice = createSlice({",
" name: '$2s',",
" initialState: $2sInitialState,",
" reducers: {",
" // Model actions as events, not setters",
" // https://redux.js.org/style-guide/#model-actions-as-events-not-setters",
" $2Added: $2sAdapter.addOne,",
" $2Removed: $2sAdapter.removeOne,",
" $0",
" },",
"});",
"",
"export const { $2Added, $2Removed } = $2sSlice.actions;",
""
],
"description": "rtk slice"
},
"rtk selectors": {
"prefix": "rtkselectors",
"body": [
"import { IApplicationState } from 'types/applicationstate';",
"",
"import { ${2:${TM_DIRECTORY/^.+\\\\/(.*)$/${1:/camelcase}/}}sAdapter } from './slice';",
"",
"// Define selectors alongside reducers:",
"// See: https://redux.js.org/usage/deriving-data-selectors#define-selectors-alongside-reducers",
"",
"export const $2sSelectors = $2sAdapter.getSelectors<IApplicationState>((state) => state.$2s);",
"",
"// Name selector functions as \"selectThing\"",
"// See: https://redux.js.org/style-guide/#name-selector-functions-as-selectthing",
"export const { selectAll: select${3:${TM_DIRECTORY/^.+\\\\/(.*)$/${1:/pascalcase}/}}s, selectById: select$3ById } = $2sSelectors;",
""
],
"description": "rtk slice"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment