I'm new in ReactJS. But used to with VueJS. Previously, I was developing the projects in VueJS. But in ReactJS, I'm facing difficulty in setting pagination where I want something like this.
Whenever user changes search value, it should reset the page number to 1 and make API call to fetch results.
This is making trouble for me. Can anyone help here please?
The problem is if I change search value for multiple times without changing page, it's not making API call again because page value is not changed. Here is my code.
import React, {useCallback, useEffect, useState, useMemo, useRef} from 'react';
import {useHistory, useLocation} from "react-router-dom";
import _ from 'lodash';
const queryString = require('query-string');
import {Page, Card, DataTable, Filters, Link, Stack, Pagination, Spinner} from '@shopify/polaris';
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
export default function App() {
const params = queryString.parse(location.search);
const [from, setFrom] = useState(0);
const [to, setTo] = useState(0);
const [total, setTotal] = useState(0);
const [hasPrevious, setHasPrevious] = useState(false);
const [hasNext, setHasNext] = useState(false);
const [page, setPage] = useState(params.page ? parseInt(params.page) : 1);
const [queryValue, setQueryValue] = useState(params.search ? params.search : null);
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(true);
const queryParams = useMemo(() => {
let queryParamsObject = {};
if (page > 1) queryParamsObject.page = page;
if (queryValue) queryParamsObject.search = queryValue;
return queryParamsObject;
}, [page, queryValue]);
const prevPage = usePrevious(page);
const prevQueryValue = usePrevious(queryValue);
const handleFiltersQueryChange = useCallback((value) => setQueryValue(value), []);
const handleQueryValueRemove = useCallback((value) => setQueryValue(null),[]);
const handleFiltersClearAll = useCallback(() => handleQueryValueRemove(), [handleQueryValueRemove]);
const rows = useMemo(() => {
return items.map(item => {
return [
<Link removeUnderline url={`/items/${item.id}`}>{item.title}</Link>,
item.email
];
});
}, [items]);
const fetchItems = useCallback((params) => {
setLoading(true);
window.axios.get(`/items`, {params}).then((response) => {
setItems(response.data.data);
setFrom(response.data.from);
setTo(response.data.to);
setTotal(response.data.total);
setHasPrevious(Boolean(response.data.prev_page_url));
setHasNext(Boolean(response.data.next_page_url));
setLoading(false);
});
}, []);
const debouncedSearch = useCallback(_.debounce((params) => {
if (params.page === page) {
history.push({pathname: '/items', search: queryString.stringify(params)});
fetchItems(params);
} else {
setPage(1);
}
}, 1000), []);
useEffect(() => {
if (typeof prevQueryValue !== "undefined" && prevQueryValue !== queryValue) {
debouncedSearch(queryParams);
} else {
history.push({pathname: '/items', search: queryString.stringify(queryParams)});
fetchItems(queryParams);
}
}, [page, queryValue]);
return (
<Filters
queryValue={queryValue}
filters={[]}
onQueryChange={handleFiltersQueryChange}
onQueryClear={handleQueryValueRemove}
onClearAll={handleFiltersClearAll}
queryPlaceholder="Filter items"
/>
<DataTable
columnContentTypes={[
'text',
'text',
]}
headings={[
'Col1',
'Col2',
]}
rows={rows}
footerContent={`Showing ${from} to ${to} of ${total} results`}
/>
{hasPrevious || hasNext ? <div className="pagination"><Stack distribution="center"><Pagination hasPrevious={hasPrevious} hasNext={hasNext} onPrevious={() => setPage(parseInt(page) - 1)} onNext={() => setPage(parseInt(page) + 1)} /></Stack></div> : null}
);
}