I'm writing a custom pagination hook that'll fetch an API and will return some data to me like React Query. Fairly simple. What I'm trying to do is to trigger that hook when a state(in this case cursor) updates.
Here's the hook itself:
import axios from "../api/axios";
import { useEffect, useRef, useState } from "react";
interface FetchInfiniteResourceProps {
// The URL of the API endpoint
url: string;
// Cursor of the page
cursor: number;
// Parameter with which the backend accepts the cursor number
queryParam: string;
// The property on the response which will indicate if the next page exists
nextPageParam: string;
// Other config
config: {
enabled: boolean;
};
}
// Prop types for useFetchInfiniteResource
interface StateProps {
data: any[];
isLoading: boolean;
hasNextPage: boolean;
isFetchingNextPage: boolean;
}
/**
* This function will be used for fetching
* an infinite resource from the back-end
*/
export const useFetchInfiniteResource = ({
url,
cursor,
queryParam,
nextPageParam,
config: { enabled },
}: FetchInfiniteResourceProps) => {
// Creating a new state
const [state, setState] = useState<Partial<StateProps>>({
data: [],
isLoading: true,
hasNextPage: false,
isFetchingNextPage: false,
});
// Method for setting the data
const setData = (newState: []) => setState({ data: newState });
// The function for sending the request
const request = async () => {
// If it's not the first time that this request has triggered
if (!state.isLoading) setState({ ...state, isFetchingNextPage: true });
// Sending the request
const { data: response } = await axios.get(url, {
params: {
// Query paramter
[queryParam]: cursor,
},
});
// Updating the state
setState({
// If it's the first time that this request is invoked
isLoading: state?.isLoading && false,
// Merging the data
data: state?.data?.concat(response.data),
// Checking if the next page exists
hasNextPage: response[nextPageParam] !== null,
// If it's not the first time that the request is invoked then set it to false
isFetchingNextPage: !state?.isLoading && false,
});
};
const requestRef = useRef(async () => await request());
useEffect(() => {
if (enabled) requestRef.current();
}, [enabled]);
// Returning all the items from the state and the function to update the data manually
return { ...state, setData };
};
And here's the component:
const SomeComponent = () => {
const [cursor, setCursor] = useState(0);
const {...} = useFetchInfiniteResource({ cursor, ... }); // Problem here
someListener(() => {
setCursor(cursor + 1); // Problem here
});
return ...
}
I think I'm misusing the useEffect or the useRef hook, but so far I have tried also using the useCallback hook.
Thanks for your help