skip to Main Content

I created a button that changes my route and adds a search param to the URL.

The functionality of the button is as so:

import { Link } from "react-router-dom";

<Link to={`/route/locations?openCertainModal=true`}>
  {placeholder}
</Link>

My problem occurs when I am already in the located in /route/locations. When I click the button and I’m there, the route will change from /route/locations to /route/locations?openCertainModal=true, but since the component is already mounted, no rerender is triggered. How can I trigger a rerender of the component when ?openCertainModal=true is added to the route and window.location.search changes?

I’m using react-router-dom 5.x.x

2

Answers


  1. Chosen as BEST ANSWER

    Based on Drew's answer, I made this hook to allow getting and setting the URL search params:

    import { useMemo } from "react";
    import { useHistory, useLocation } from "react-router-dom";
    
    //A similar function is implemented in react-router-dom v6, but we are using v5 at time of writing
    function useSearchParams() {
      const { search } = useLocation();
      const history = useHistory();
    
      const searchParams = useMemo(() => new URLSearchParams(search), [search]);
    
      function setSearchParams(key: string, value: string | number | boolean, reload?: boolean) {
        searchParams.set(key, value.toString());
    
        if (reload) {
          //reloads the page
          window.location.search = searchParams.toString();
        } else {
          history.push(window.location.pathname + "?" + searchParams.toString());
        }
      }
    
      return { searchParams, setSearchParams };
    }
    
    export default useSearchParams;
    

  2. Use the useSearchParams hook in the target component, when the matched route’s URL path + searchParams update it should trigger a component rerender.

    Basic React-Router-DOM v6 Example:

    import { useEffect } from "react";
    import { Routes, Route, Link, useSearchParams } from "react-router-dom";
    
    const RouteLocations = () => {
      const [searchParams] = useSearchParams();
    
      ...
    
      return (
        ...
      );
    };
    
    <Route path="/route/locations" element={<RouteLocations />} />
    

    enter image description here

    Basic React-Router-DOM v5 Example:

    Use the location.search value. It’s common to abstract this logic into a custom hook.

    import { useEffect, useMemo } from "react";
    import { Switch, Route, Link, useLocation } from "react-router-dom";
    
    const useSearchParams = () => {
      const { search } = useLocation();
    
      const searchParams = useMemo(() => new URLSearchParams(search), [search]);
    
      return [searchParams];
    };
    
    const RouteLocations = () => {
      const [searchParams] = useSearchParams();
    
      useEffect(() => {
        console.log("RouteLocations rendered", searchParams.toString());
      });
    
      return (
        ...
      );
    };
    
    <Route path="/route/locations" component={RouteLocations} />
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search