Search code examples
reactjsmern

When i refresh page my URL back to initial values in MERN stack


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


Solution

  • 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
          />
        </>
      )
    }