Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing nested params with useParams #409

Closed
pReya opened this issue Jan 23, 2024 · 11 comments · Fixed by #461
Closed

Accessing nested params with useParams #409

pReya opened this issue Jan 23, 2024 · 11 comments · Fixed by #461
Labels

Comments

@pReya
Copy link

pReya commented Jan 23, 2024

Hello, I have a component setup that looks something like this:

<Provider value={client}>
  <!-- some more stuff here -->
  <Route path="/admin" nest>
    <Switch>
      <Route path="/">
        <RedirectToCompany />
      </Route>
      <Route path="/:companyId" nest>
        <AdminLayout menu={menu}>
          <Switch>
            <Route path="/seminare">
              <SeminarPage />
            </Route>
          </Switch>
        </AdminLayout>
      </Route>
    </Switch>
  </Route>
</Provider>

I'd like to access my companyId param within my <SeminarPage> component, which is nested inside another route, via useParams(). However I always get an empty object. I assume because useParams() will always use the params from the closest ancestor <Route> component. With nested routes, is there any way to access "higher up" params?

@molefrog
Copy link
Owner

Hi @pReya, I don't think it's possible at the moment. In the current design, the context where parameters are stored gets overwritten in the Route, so parameters don't inherit.

@larpo
Copy link

larpo commented Jan 30, 2024

The way it currently works is pretty counterintuitive and makes using nested routes not an option in many cases.

Intuitively something like this should work, and does work at least in react-router.

<Route path="/:dataset" nest>
    <Route path="/">
        <ChartPicker />
    </Route>
    <Route path="/:type">
        <Chart />
    </Route>
</Route>;

Merging existing params to the params context in Route seems pretty small change, is that something that could be added at this point?

@molefrog
Copy link
Owner

molefrog commented Jan 30, 2024

I see. Your point is fair enough. I'm finalising everything for the v3 release (it's been in the rc for over 2 m already, so really want to publish it soon). Since it isn't a breaking change, perhaps we can get back to it in the next minor release?

@larpo
Copy link

larpo commented Jan 30, 2024

Minor release sounds reasonable, bit too late at this point with rc3 👍

@vicodinvic1
Copy link

The way it currently works is pretty counterintuitive and makes using nested routes not an option in many cases.

Intuitively something like this should work, and does work at least in react-router.

<Route path="/:dataset" nest>
    <Route path="/">
        <ChartPicker />
    </Route>
    <Route path="/:type">
        <Chart />
    </Route>
</Route>;

Merging existing params to the params context in Route seems pretty small change, is that something that could be added at this point?

it doesn't work like that, useParams returns just an empty object if you try to use it inside of a nested nest

@vicodinvic1
Copy link

@molefrog please add this feature, otherwise I will have to go back to react-router-dom v5 :(

@larpo
Copy link

larpo commented Mar 14, 2024

We are using these light wrappers, seem to work fine (with the downside of having to import the custom implementations instead of wouter):

import {useParams, Route} from "wouter";

type ParentParamsContextType = Record<string, string>;
const ParentParamsContext = createContext<ParentParamsContextType>({});

export function useNestedParams<T extends ParentParamsContextType>(): T {
    const parentParams = useContext(ParentParamsContext);
    const params = useParams<T>();
    return {...parentParams, ...params} as T;
}

export const CustomRoute: typeof Route = props => {
    const params = useNestedParams();
    return (
        <ParentParamsContext.Provider value={params}>
            <Route {...props} />
        </ParentParamsContext.Provider>
    );
};

@mattkrins
Copy link

Kinda bizarre this is not already possible...
This library is pretty much perfect in every way, except for this.

@molefrog
Copy link
Owner

@mattkrins I know... This feature isn't hard to implement, however this will require every Route in the app to subscribe to the context to get the outer parameters. It will mean that every route down the tree will re-render even if it was wrapped in memo. It's a performance trade-off that we will have to consider.

@molefrog
Copy link
Owner

Ok, actually I am wrong. Thoughts:

  1. Parameters only change when the current location changes (probably, I can't think of an edge-case)
  2. Every route is also subscribed to current location, so it will re-render anyway

@molefrog
Copy link
Owner

Released in https://github.com/molefrog/wouter/releases/tag/v3.3.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants