0

I want to make search request to the api. but problem I'm having is that every time URLSearchParams gets updated. the searchKeyword does not update. I mean it's not rerendering. and when i refresh the page i want to send the request with updated value. but I want to rerender the searchKeyword everytime the value = new URLSearchParams(window.location.search).get("query") update.

    const [searchKeyword, setSearchKeyword] = useState("")
   
    let value = new URLSearchParams(window.location.search).get("query")

    useEffect(() => {
        setSearchKeyword(value)
        axios.get(`http://127.0.0.1:8000/music/api/searchtrack/?search=${searchKeyword}`)
            .then(res => {
                setSongs(res.data)
            }).catch(err => {
                console.log(err)
            })
        }, [searchKeyword])
Amisha Mundra
  • 47
  • 1
  • 9

2 Answers2

1

You need something that listens to window.location, one option is to use useLocation from react-router-dom and use the location object in your useEffect.

This would be a full example based on your code

import React, { useEffect, useState } from 'react';

const mockFetch = path => {
  return new Promise(res => {
    setTimeout(() => {
      console.log(path);
      res({
        path,
        data: [1, 2, 3]
      });
    }, 500);
  });
};

const useSearch = () => {
  const [search, setSearch] = React.useState(window.location.search);
  const listenToPopstate = () => {
    const searchPath = window.location.search;
    setSearch(searchPath);
  };
  React.useEffect(() => {
    window.addEventListener('popstate', listenToPopstate);
    return () => {
      window.removeEventListener('popstate', listenToPopstate);
    };
  }, []);
  return search;
};

export default function App() {
  const search = useSearch();
  const [songs, setSongs] = useState([]);

  useEffect(() => {
    let value = new URLSearchParams(search).get('query');
    const g = async () => {
      try {
        const data = await mockFetch(
          `http://127.0.0.1:8000/music/api/searchtrack/?search=${value}`
        );
        setSongs(data);
      } catch (err) {
        console.log(err);
      }
    };
    g();
  }, [search]);

  return (
    <div>
      <h1>Hello StackBlitz!</h1>
      <p>{JSON.stringify(songs)}</p>
    </div>
  );
}

This example is not production ready, to make it production ready:

  • See if you can replace the useSearch by a 3rd party library you are using (are you using a router library), otherwise it's ok to use something like this.
  • Add a cancellable event to the get request so that it doesn't trigger setSongs when the user navigates away from the page.
Claudiordgz
  • 3,023
  • 1
  • 21
  • 48
  • If you're already using `react-router-dom`, you can greatly simplify by doing something like this: https://dev.to/brenonovelli/usequery-with-react-router-dom-5ha1. – Brian Thompson Jun 02 '21 at 17:12
  • @BrianThompson this is the way to get the value. but I already have the value it's just not updating. – Amisha Mundra Jun 02 '21 at 17:24
  • @AmishaMundra you would need to listen to location from `const location = useLocation();` and retrieve the value from the `location` variable when it changes. – Claudiordgz Jun 03 '21 at 04:02
-1

This is because useEffect hook renders when only dependency array changes.You will have to put this line in side use effect hook.

let value = new URLSearchParams(window.location.search).get("query")
Gulshan Aggarwal
  • 954
  • 1
  • 7
  • 13
  • this will cause an infinite loop – Claudiordgz Jun 02 '21 at 16:43
  • @Claudiordgz exactly that's what is happening – Amisha Mundra Jun 02 '21 at 16:43
  • @AmishaMundra you need something like this: https://stackoverflow.com/a/58443076/1963929 – Claudiordgz Jun 02 '21 at 16:46
  • Basically listen to window.location changes, and change a setState hook when its the value you need. That will trigger a refresh you can listen to. In your example, you are listening to changes to searchKeyword and inside of it you setSearchKeyword, which retriggers the same useEffect, causing that infinite loop. – Claudiordgz Jun 02 '21 at 16:49