I use the MERN stack and I want to create something like this on the frontend: http://localhost:3000/products?color=0000&sort=latest&category=man etc. I'm using the redux toolkit and my getProductSlice looks like this:
export const getProducts = createAsyncThunk(
'product/get',
async ({ page, sort, localValue, colorFilter, categoryFilter }, thunkAPI) => {
let colorStr = colorFilter.substring(1);
let url = `/api/v1/products?page=${page}&sort=${sort}&color=${colorStr}&cat=${categoryFilter}`;
if (localValue) {
url = url + `&search=${localValue}`;
}
try {
const { data } = await axios.get(url);
return data;
} catch (error) {
const message = error.response.data.msg;
return thunkAPI.rejectWithValue(message);
}
}
);
My ProductPage looks like this:
const dispatch = useDispatch();
const {
products,
isLoading: loadingProducts,
search,
sort,
numOfPages,
page,
sortOptions,
uniqueColors,
colorFilter,
categoryFilter,
} = useSelector(state => state.product);
console.log(colorFilter, categoryFilter);
useEffect(() => {
dispatch(getCategories());
}, [dispatch]);
const { categories } = useSelector(state => state.category);
const [localSearch, setLocalSearch] = useState('');
const [localValue] = useDebounce(localSearch, 1000);
const [value, setValue] = useState(sort);
useEffect(() => {
const queryParams = {
page: page,
sort: sort,
localValue: localValue,
colorFilter: colorFilter,
categoryFilter: categoryFilter,
};
const searchParams = new URLSearchParams(queryParams);
const queryString = searchParams.toString();
window.history.replaceState(null, null, `/products?${queryString}`);
dispatch(getProducts(queryParams));
}, [dispatch, page, search, sort, localValue, colorFilter, categoryFilter]);
Everything is working fine, my URL changing when i search, page, select color etc. but when i go to page=2 when i refresh page my URL back to initial page=1, and every filter
default value of page, sort, search,... should be take from searchParams first
below is my usual code:
import React, { useState } from "react";
import qs from "query-string";
import { useLocation, useHistory } from "react-router-dom";
export default function List() {
const location = useLocation();
const history = useHistory();
const searchParams = qs.parse(location.search, { parseNumbers: true });
const [sort, setSort] = useState(searchParams.sort || "desc");
const [sortBy, setSortBy] useState(searchParams.sortBy || "id");
const [page, setPage] = useState(searchParams.page || 0);
useEffect(() => {
const search = {
sort,
sortBy,
page
};
history.replace({ search: qs.stringify(search, { arrayFormat: "comma" }) });
}, [sort, sortBy, page, history]);
const onChangePage = (event, newPage) => {
setPage(newPage);
};
//similar for onChangeSort, onChangeSortBy
return (
<>
...
<ListTableForm
page={page}
sort={sort}
sortBy={sortBy}
onChangePage={onChangePage}
// onChangeSort, onChangeSortBy
/>
</>
)
}