Last active
March 21, 2023 10:57
-
-
Save TyT-NICK/add56d7fdbc40fa88884329e3b753d4e to your computer and use it in GitHub Desktop.
Example: Redux-tk queries with code-splitting
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import isEqual from 'lodash/isEqual'; | |
import uniqWith from 'lodash/uniqWith'; | |
import { GRAPHQL_QUERY } from 'utils/contentful/graphqlQuery'; | |
import { | |
getGraphqlResultArticles, | |
getGraphqlResultArticlesByTags, | |
getGraphqlResultTags, | |
getGraphqlResultTotalArticlesCount, | |
getGraphqlResultTotalArticlesCountByTags, | |
} from 'utils/contentful/helper'; | |
import { contentfulClient } from 'utils/contentful/client'; | |
import { getDocumentFields } from 'utils/helper'; | |
import { SEARCH_ARTICLES_LIMIT } from 'utils/constants'; | |
import { handleError } from 'utils/error'; | |
import baseApi, { BASEQUERY_TYPES } from '.'; | |
const blogApi = baseApi.injectEndpoints({ | |
endpoints: (builder) => ({ | |
getArticlesList: builder.query({ | |
extraOptions: { | |
type: BASEQUERY_TYPES.graphql, | |
}, | |
query({ | |
slug, | |
skip, | |
limit, | |
isTag = false, | |
order = '[publishedAt_DESC]', | |
}) { | |
return isTag | |
? GRAPHQL_QUERY.loadPreviewArticlesByTags({ | |
limit, | |
skip, | |
where: { slug }, | |
}) : GRAPHQL_QUERY.loadPreviewArticles({ | |
skip, | |
limit, | |
order, | |
}); | |
}, | |
transformResponse(response, _, { isTag }) { | |
return { | |
items: isTag | |
? getGraphqlResultArticlesByTags(response) | |
: getGraphqlResultArticles(response), | |
total: isTag | |
? getGraphqlResultTotalArticlesCountByTags(response) | |
: getGraphqlResultTotalArticlesCount(response), | |
}; | |
}, | |
}), | |
getTags: builder.query({ | |
query() { | |
return GRAPHQL_QUERY.loadTag({}); | |
}, | |
transformResponse(response) { | |
return getGraphqlResultTags(response); | |
}, | |
}), | |
getArticle: builder.query({ | |
extraOptions: { | |
type: BASEQUERY_TYPES.getEntries, | |
}, | |
async queryFn({ slug }, _, __, baseQuery) { | |
const article = (await baseQuery({ contentType: 'article', query: { slug } })).data.items[0]; | |
const { | |
publishedAt, | |
tagsList, | |
} = getDocumentFields(article, ['tagsList', 'publishedAt']); | |
const [next, prev, related] = await Promise.all([ | |
contentfulClient.graphql(GRAPHQL_QUERY.getNearbyArticle({ | |
limit: 1, | |
order: '[publishedAt_DESC]', | |
where: { publishedAt_lt: publishedAt }, | |
})), | |
contentfulClient.graphql(GRAPHQL_QUERY.getNearbyArticle({ | |
limit: 1, | |
order: '[publishedAt_DESC]', | |
where: { publishedAt_gt: publishedAt }, | |
})), | |
contentfulClient.graphql(GRAPHQL_QUERY.getRelatedArticles({ | |
limit: 10, | |
where: { slug: tagsList[0].fields.slug }, | |
})), | |
]); | |
return { | |
data: { | |
article, | |
next: getGraphqlResultArticles(next)?.[0] || {}, | |
prev: getGraphqlResultArticles(prev)?.[0] || {}, | |
related: getGraphqlResultArticlesByTags(related), | |
}, | |
}; | |
}, | |
}), | |
getDraftArticle: builder.query({ | |
extraOptions: { | |
isPreview: true, | |
type: BASEQUERY_TYPES.getEntries, | |
}, | |
query(slug) { | |
return { contentType: 'article', query: { slug } }; | |
}, | |
transformResponse(response) { | |
return response.items[0]; | |
}, | |
}), | |
getSearchResult: builder.query({ | |
async queryFn(value, _, __, baseQuery) { | |
if (!value) { | |
return { data: [] }; | |
} | |
try { | |
const [byTagRaw, byText] = await Promise.all([ | |
baseQuery(GRAPHQL_QUERY.loadPreviewArticlesByTags({ | |
where: { title_contains: value }, | |
limit: SEARCH_ARTICLES_LIMIT, | |
})), | |
baseQuery(GRAPHQL_QUERY.loadPreviewArticles({ | |
order: '[publishedAt_DESC]', | |
limit: SEARCH_ARTICLES_LIMIT, | |
where: { | |
OR: [ | |
{ title_contains: value }, | |
{ oldBody_contains: value }, | |
{ title_contains: value }, | |
], | |
}, | |
})), | |
]); | |
const result = uniqWith([ | |
...getGraphqlResultArticlesByTags(byTagRaw.data), | |
...getGraphqlResultArticles(byText.data)], isEqual).sort((a, b) => Date.parse(a) - Date.parse(b)); | |
return { data: result }; | |
} catch (e) { | |
handleError(e); | |
return { error: e.message }; | |
} | |
}, | |
}), | |
}), | |
}); | |
export const { | |
useGetArticlesListQuery, | |
useGetTagsQuery, | |
useGetArticleQuery, | |
useGetSearchResultQuery, | |
useGetDraftArticleQuery, | |
} = blogApi; | |
export default blogApi; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// It's important to import createApi from /query/react (not just /query) if you use React | |
// Without it you won't be able to use auto-generated hooks | |
import { createApi } from '@reduxjs/toolkit/dist/query/react'; | |
import { HYDRATE } from 'next-redux-wrapper'; | |
import { contentfulClient, contentfulPreviewClient } from 'utils/contentful/client'; | |
export const BASEQUERY_TYPES = { | |
graphql: 'graphql', | |
getEntries: 'getEntries', | |
}; | |
async function baseQuery(args, _, { | |
isPreview = false, | |
type = BASEQUERY_TYPES.getEntries, | |
} = {}) { | |
const client = isPreview ? contentfulPreviewClient : contentfulClient; | |
try { | |
const result = await client[type](args); | |
return { data: result }; | |
} catch (e) { | |
return { error: e.meesage }; | |
} | |
} | |
const baseApi = createApi({ | |
reducerPath: 'api', | |
baseQuery, | |
extractRehydrationInfo(action, { reducerPath }) { | |
if (action.type === HYDRATE) { | |
return action.payload[reducerPath]; | |
} | |
}, | |
endpoints: () => ({}), | |
}); | |
export default baseApi; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment