pbeshai / use-query-params

React Hook for managing state in URL query parameters with easy serialization.

Home Page:https://pbeshai.github.io/use-query-params

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Back button doesn't trigger re-render when using `WindowHistoryAdapter`

wayne530 opened this issue · comments

I'm not sure if WindowHistoryAdapter is officially supported - there are no docs and it seems very few people discussing its usage. However, it's still part of the package and a much simpler solution when React Router isn't needed. When using the back/forward browser buttons, I can see the location updating correctly, but this doesn't seem to trigger a re-render. Is that expected when using this adapter? Is the fix then to use React Router?

index.js is initialized as follows:

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <ApolloProvider client={client}>
      <QueryParamProvider adapter={WindowHistoryAdapter}>
        <App />
      </QueryParamProvider>
    </ApolloProvider>
  </React.StrictMode>
);

and <App /> makes use of useQueryParam.

Generally you'll want something else that monitors the URL and forces your app to re-render, this is something typically provided by a router package. The history package from react-router does this if you want to avoid a full router solution. Maybe you can use it similar to how the reach router example is set up. Then you'd just need to have your app re-render when the history changes (see history.listen). The window adapter provided here is likely too basic to be very useful in an modestly complex scenario.

Thanks @pbeshai. I had a chance to look through the adapter and saw that it's just manipulating window.location and so of course that's why it's not triggering any re-renders.

ok, i stumble upon this too .. couldn't understand why the app didn't re-render when changing the url param..
maybe we can add a small note around the WindowHistoryAdapter ....
how to achieve that

for the moment i bump a random state at the same time .... but it's not ideal

That's pity. The whole idea why I wanted to use this package is to have query params as single source of truth. I don't need to overengineer with router since I need to track only query params, pages are served from backend.

Found that it's easer to fall back to simple useState, using queries like initial state params and updating with both setState and setQuery.

But actually to re-render on Back button as well as on updating params, all you need in your app is:

let [query, setQuery] = useQueryParams(queryParams);
let [, setLocation] = useState(location.search);

let setQueryParams: typeof setQuery = (params) => {
   setQuery(params);
   setLocation(location.search);
};

useEffect(() => {
   let updateLocation = () => setLocation(location.search);
   window.addEventListener('popstate', updateLocation);
   return () => window.removeEventListener('popstate', updateLocation);
}, []);

and use setQueryParams instead of setQuery further.