API:
import {
createApi,
fetchBaseQuery,
} from '@reduxjs/toolkit/query/react'
import { RootState } from 'store'
export interface FeedType {
id: string
title: string
imgUrl: string
}
export const feedsApi = createApi({
reducerPath: 'feeds',
tagTypes: ['Feeds'],
baseQuery: fetchBaseQuery({
baseUrl: 'http://localhost:5000',
}),
endpoints: (build) => ({
getFeedsMore: build.query<FeedType[], void>({
async queryFn(arg, queryApi, extraOptions, baseQuery) {
const state = queryApi.getState() as RootState
const selector = feedsApi.endpoints.getFeedsMore.select() as (
state: any
) => any
const result = selector(state) as { data: FeedType[] } | undefined
const oldData = (result?.data ?? []) as FeedType[]
const { data } = await baseQuery({
url: 'feeds?_page=' + Math.round(oldData.length / 10 + 1),
})
return { data: [...oldData, ...(data as FeedType[])] }
},
}),
}),
})
export const {
useGetFeedsMoreQuery,
} = feedsApi
Component:
import FeedItem from 'components/FeedItem'
import React from 'react'
import Masonry from 'react-masonry-css'
import { useGetFeedsMoreQuery } from 'services/feeds'
interface FeedsMorePageProps {}
const FeedsMorePage: React.FunctionComponent<FeedsMorePageProps> = () => {
const { isLoading, data: feeds, refetch } = useGetFeedsMoreQuery()
return (
<>
{isLoading ? (
'loading'
) : (
<>
<Masonry
breakpointCols={{
default: 3,
1100: 2,
700: 1,
}}
className="my-masonry-grid"
columnClassName="my-masonry-grid_column"
>
{feeds &&
feeds.map((feed) => <FeedItem key={feed.id} feed={feed} />)}
</Masonry>
<button className="btn btn-info" onClick={() => refetch()}>
Load More...
</button>
</>
)}
</>
)
}
export default FeedsMorePage
I know it is totally a mess, this is the only clumsy way I could make it run.
What is the best practice to this scenario?
It is common to use dispatch and getState in a Thunk-Action, but the most confusing part to me is in queryFn I have getState and endpoint.select methods, but I do not know how to type them in typescript.
feedsApi.endpoints.getFeedsMore.select()(state as RootState)
// this gives me a super long type incompatible complain
I can not use useSelector hook here neither, util I made out this ugly way...