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

react-router v6: warning You should call navigate() in a React.useEffect

d9k opened this issue · comments

Used RouteAdapter example:
https://github.com/pbeshai/use-query-params/blob/master/examples/react-router-6/src/index.js
#196 (comment)

My component code:

const MyComponent = () => {
  const [filter, setFilter] = useQueryParam('filter', ObjectParam);

  useEffect(() => {
    if (!filter) { {
      setFilter({ city: 'London' });
    }
  }, [filter, setFilter]);

Getting an error:

You should call navigate() in a React.useEffect(), not when your component is first rendered

And redirect doesn't work.

Temporary solution

const MyComponent = () => {
  const [firstRenderDone, setFirstRenderDone] = useState(false);
  const [filter, setFilter] = useQueryParam('filter', ObjectParam);

  useEffect(() => {
    if (firstRenderDone && !filter) { {
      setFilter({ city: 'London' });
    }
  }, [filter, firstRenderDone, setFilter]);

  useEffect(() => {
    setFirstRenderDone(true);
  }, []);

How can I improve RouteAdapter to not implement firstRenderDone hack in every component I need redirect as soon as possible?

Any updates? :)

Any updates? :)

I am using the RouteAdapter fix as provider here:
https://www.robinwieruch.de/react-router-search-params/

You could also check out the port of useQueryParams which uses react-router's API (i.e. useSearchParams) directly
https://github.com/mcctomsk/react-router-url-params#usequeryparams

Hi there, support for React Router 6 has been added to v2.0.0-rc.0. Give it a shot and let me know if you still run into issues. See the changelog for migration info.

Any updates? :)

I am using the RouteAdapter fix as provider here: https://www.robinwieruch.de/react-router-search-params/

can you be more specific? i can't see anything about setting URL parameter right on the first render

i bumped into the same issue when wanting to change invalid URL params on the first render and this is my ugly HOTFIX w/ setTimeout:

const [pageNumber, setPageNumberUrlParam] = useQueryParam('page', withDefault(NumberParam, 0));

React.useEffect(() => {
    const validPageNumber = validatePageNumber(pageNumber);
    if (pageNumber !== validPageNumber) {
        setTimeout(() =>
            setPageNumberUrlParam(validPageNumber, 'replaceIn')
        );
    }
}, []);

Similar issue here

You should call navigate() in a React.useEffect(), not when your component is first rendered.

i get the same warning also with the ReactRouter6Adapter.

@pbeshai this seems to still be an issue. This isn't just a warning in practice - react-router warns, then ignores the navigate call - https://github.com/remix-run/react-router/blob/main/packages/react-router/lib/hooks.tsx#L181-L187

The issue comes from the order in which react executes effects (which was a surprise to me, but makes sense). Also not sure if this order is actually guaranteed...
https://codesandbox.io/s/priceless-pond-ck7gdn?file=/src/App.js

Effects in the child get executed before effects in the parent (but in order within a component). Because of how this library uses useNavigate in the provider (via the adapter), any effect in a child of the provider will execute before the effect in useNavigate, so the activeRef has not been set. Feels like this is basically from using useLocation in a way they haven't envisioned.

I'm not sure if there's a good way to handle this in use-query-params. A workaround for user code is to put the param setter in setTimeout. enableBatching: true also solves this because it does a similar thing, but marked as experimental so 🤷

@pbeshai Can we reopen this issue?

We're having the same problem, and have solved/worked around it by using a modified ReactRouter6Adapter which wraps the navigate function so that any immediate calls to it are enqueued for future execution, and the queue is processed from a useEffect(). See PR: #266