I have a few rtk query mutation functions that do similar requests.
It is is about various searches:
- useSearchUsersMutation
- useSearchCitiesMutation
- useSearchCountriesMutation
- ...
Results from all function include at least following properties:
- id
- name
I would like to build an "suggestions" input component, but i don't want to have separate components for each mutation hook just to satisfy typescript.
So i built a general search component with input field and results dropdown. Then pass rtk query mutation function as props from parent component where i need search with suggestions (as user types results are shown bellow input).
My implementation works but i get stuck with typescript props typing.
My SuggestionInput.tsx
component:
import { useState, useEffect } from 'react';import { useDebounce } from '../lib/hooks/useDebounce';import { Input } from './Input';import { clsx } from 'clsx';type Props = { useSearch: any; // <- How to type "general" rtk query mutation hook function onUpdate: (data: any) => void; // <- How to type return result based on mutation hook};export function SuggestionInput({ useSearchMutation, onUpdate }: Props) { const [searchQuery, setSearchQuery] = useState(''); const [searchResults, setSearchResults] = useState([]); const [search, { data, isError, isLoading }] = useSearch(); const debouncedSearch = useDebounce(searchQuery); useEffect(() => { setSearchResults(data ? data : []); }, [data]); useEffect(() => { if (debouncedSearch.length >= 3) { search(debouncedSearch); } else { setSearchResults([]); } }, [debouncedSearch]); return (<div className={clsx('relative')}><Input small onChange={(e) => setSearchQuery(e.target.value)} /> {!!searchResults?.length && (<div className={clsx('absolute', 'top-8')}> {searchResults.map((result: any) => ( // <- How to get results type<div key={result.id} onClick={() => onUpdate(result)}> {result.name}</div> ))}</div> )}</div> );}
Usage in the parent component:
import { useSearchUsersMutation, useSearchCitiesMutation, useSearchCountriesMutation } from '../lib/Queries';export function ParentComponent() { const update = (mode: string, data: any) => { // <- How to type expected returned data console.log(mode, data); } return (<><SearchInput useSearch={useSearchUsersMutation} onUpdate={(data: any) => update('users', data)} /><SearchInput useSearch={useSearchCitiesMutation} onUpdate={(data: any) => update('cities', data)} /><SearchInput useSearch={useSearchCountriesMutation} onUpdate={(data: any) => update('countries', data)} /></> );}
Is my approach even possible to type or should i take different approach to tackle my problem?
Should i use like a general type for search with shared properties and then extend it with additional properties for each search queries?
While my solution works great i don't like to use any
types and some help from intellisense would be nice as well. So that is why I ask you for help. Thanks!