最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to watch if the querystring changes within React Router v6? - Stack Overflow

programmeradmin3浏览0评论

I've a form with a drop down on it, when I select the drop down I push the value onto the querystring. When the url with that querystring is first hit it stores the querystring param into state and then uses it to populate the drop down. This all works as intended. My issue is triggering the form to see changes to the querystring while still on the same page.

If I'm already on the page but then click a react router Link to the same page but with a different query string parameter it doesn't catch/see that it has changed. I'm wondering how to watch the querystring for changes or if there is a better way to handle this.

I've found that you can listen to the history object that React-Router is meant to use under the hood but I've had little success with this and again I'm not sure if this is the right way to go .md

I've tried adding the following to the page but the listener never seems to fire when I change the querystring (aka search) of the url. Wonder what I'm missing?

  useEffect(() => {
    // Listen for changes to the current location.
    console.info("wiring up history listener");
    let unlisten = history.listen(({ location, action }) => {
      console.info("HISTORY CHANGED", location.search);
      console.log(action, location.pathname, location.state);
      // Plan was to update my state here if needed
    });

    return unlisten;
  }, []);

Using react-router-dom v6.

I've a form with a drop down on it, when I select the drop down I push the value onto the querystring. When the url with that querystring is first hit it stores the querystring param into state and then uses it to populate the drop down. This all works as intended. My issue is triggering the form to see changes to the querystring while still on the same page.

If I'm already on the page but then click a react router Link to the same page but with a different query string parameter it doesn't catch/see that it has changed. I'm wondering how to watch the querystring for changes or if there is a better way to handle this.

I've found that you can listen to the history object that React-Router is meant to use under the hood but I've had little success with this and again I'm not sure if this is the right way to go https://github.com/ReactTraining/history/blob/master/docs/getting-started.md

I've tried adding the following to the page but the listener never seems to fire when I change the querystring (aka search) of the url. Wonder what I'm missing?

  useEffect(() => {
    // Listen for changes to the current location.
    console.info("wiring up history listener");
    let unlisten = history.listen(({ location, action }) => {
      console.info("HISTORY CHANGED", location.search);
      console.log(action, location.pathname, location.state);
      // Plan was to update my state here if needed
    });

    return unlisten;
  }, []);

Using react-router-dom v6.

Share Improve this question edited Feb 3, 2022 at 1:39 Drew Reese 203k17 gold badges236 silver badges268 bronze badges asked Jan 10, 2021 at 22:44 Pete DuncansonPete Duncanson 3,2463 gold badges26 silver badges35 bronze badges 3
  • You're passing an empty dependency array to useEffect so it will only ever run on the first render. Also, the return of a useEffect is a callback that will be run before unmounting when a rerender is triggered. – pilchard Commented Jan 10, 2021 at 23:04
  • Your looking for useHistory, useParams, or useLocation depending on your needs. They already exist, no need to roll your own – Adam Jenkins Commented Jan 10, 2021 at 23:06
  • The hook from the question worked perfectly for me... – Rashomon Commented Sep 6, 2023 at 13:54
Add a comment  | 

4 Answers 4

Reset to default 5

If you want to listen for changes on the path's query string parameters you need to "listen" for changes to them from the location object. Use the useLocation hook to get the location object.

location

{
  key: 'ac3df4', // not with HashHistory!
  pathname: '/somewhere',
  search: '?some=search-string',
  hash: '#howdy',
  state: {
    [userDefined]: true
  }
}

Listen for changes using effect hook.

const { search } = useLocation();

useEffect(() => {
  // search query string changed
}, [search]);

Your code doesn't work because react-router uses a different instance of history so your custom listeners aren't fired when the change is made through react-router's Link (it gets handled by a different version of history). However, clicking on the browser's forward or back buttons should trigger your listener since this notifies all history instances.

The best tool for your use case is useSearchParams hook

const [searchParams] = useSearchParams();

useEffect(() => {
  // code for handling search query change
}, [searchParams]);

Also, you might not need to use useEffect but treat searchParams as a source of truth for search data without creating another entity in the state.

react-router comes with all the hooks you need. Sounds to me like you want: useParams

I'm using createBrowserRouter so I'm using loaders for all my routes. I've got a child route that has pagination, so when the page is changed, I put the page query param into the URL so it can be shared. I found the useFetcher hook and I'm using fetcher.load() as shown here to trigger the loader for that route to refresh the data.

I'm updating the page using the useSearchParams hook then listening for page to change in a useEffect where I run fetcher.load() when the page changes. It works but it feels pretty cumbersome, so if anyone has a cleaner approach, I'm all ears.

发布评论

评论列表(0)

  1. 暂无评论