react-querycode-cleanupreact-tsxtanstackreact-query

React-query infiniteQuery - how to fix additional pageParam type checking


i have bumped into following issue, i'm trying to implement infiniteQuery by using react-query tanstack, but i can't do it without additional checking of pageParam on it's type of number.

Could you please tell me how can i simplify this code without affecting of files structure

ApiClient.ts

import axios from "axios";

const apiClient = axios.create({
    baseURL: 'https://jsonplaceholder.typicode.com/'
})

class API<T> {
    constructor(public endpoint: string) {
    }

    getAll = (pageParam: number) => {
       return apiClient.get<T[]>(this.endpoint, {
            params: {
                _page: pageParam
            }
        }).then(res => res.data)
            .catch(err => err)
    }
}

export default API

todo-service.ts

import API from "../api-service/api-client.ts";

export interface Todo {
    userId: number;
    id: number;
    title: string;
    completed: boolean;
}
const UseTodoService = new API<Todo>('todos')

export default UseTodoService;

useTodo hook

import {useInfiniteQuery} from "@tanstack/react-query";
import {CACHE_KEY_TODO} from "../constants.ts";
import UseTodoService, {Todo} from "../http-service/todo-service.ts";

const UseTodo = () => {
   return useInfiniteQuery<Todo[], Error>({
       queryKey: CACHE_KEY_TODO,
       queryFn: ({pageParam}) => {
           if (typeof pageParam === 'number') return UseTodoService.getAll(pageParam);
           else throw new Error("pageParam must be a number.");
       },
       getNextPageParam: (lastPage, allPages) =>
           lastPage.length > 0 ? allPages.length + 1 : undefined,
       initialPageParam: 1
   })
    }


export default UseTodo;

Todo component

import useTodo from "../hooks/useTodo.ts";

function TodoList() {
    const {data, fetchNextPage } = useTodo()
    return <>
        <h1>TodoList</h1>
        <ul className="list-group">
            {data?.pages.map(todos => todos.map((todo, index) =>
                <li className="list-group-item" key={index}>{todo.title}</li>))}
        </ul>
        <button onClick={() => fetchNextPage()} className="btn btn-primary mt-2">Fetch More</button>
    </>
}

export default TodoList;

i'm expecting help of how you can refactor this code to make it more cleaner and without additional checking type of pageParams

 queryFn: ({pageParam}) => {
           if (typeof pageParam === 'number') return UseTodoService.getAll(pageParam);
           else throw new Error("pageParam must be a number.");
       },

Solution

  • pageParam is already typed as number. You can remove additional type checking.

    When you define a variable in TypeScript with a specific type, such as initialPageParam: 1, TypeScript infers the type of that variable based on the assigned value. In this case, initialPageParam is inferred to be of type number because you've assigned it the value 1.

    The pageParam variable is also of type TPageParam, which we can infer is a type alias for number based on your usage. Therefore, you don't need to perform a typeof check on pageParam because TypeScript already knows it's a number