I’ve created two custom hooks usePagination
and useSearch
. These handle the logic for paging and searching and only expose getters/setters for the current page and search query.
Here’s how I would use them in my list component:
const List = () => {
const [currentPage, setCurrentPage] = usePagination()
const [searchQuery, setSearchQuery] = useSearch()
const queryParams = useMemo(() => ({
page: currentPage,
search: searchQuery
}), [currentPage, searchQuery])
// Pass the `queryParams` to an API endpoint to load my list items.
}
When the search query changes, I need to reset the current page to 1. Something like this:
useEffect(()=>{
setCurrentPage(1)
}, [searchQuery, setCurrentPage])
Of course, with the above logic, this results in two API calls being made. One when the search query changes and then another immediately after when the current page value is reset.
Is there any way to combine the two values from my custom hooks currentPage
and searchQuery
into a combined state so that I can update both the page number and the query simultaneously? In other words, is there anything I can do here other than scrap my individual hooks and use a single state for everything?
E.g.
const [queryState, setQueryState] = useState({
currentPage: 1,
searchQuery: ""
})
2
Answers
Yes and you almost got it right. You could do something like this:
You could even wrap it into a hook that takes the initial state and returns the getter and a modified setter. Something like the following:
and the usage for it would be:
Can you explain why you need the setState/setCurrentPage function as a dependency?
As an intended effect, whenever a useState value changes the entire component is re-rendered, and that’s why you have two API calls, because both states are causing a re-rendering.
Solution: Assuming you only want to make a new API call when searchQuery changes, and not when currentPage data changes, React provides useRef which you can use to store/update data without re-rendering and making costly API calls.
Example (in your usePagination hook):
Then in List: