react-router icon indicating copy to clipboard operation
react-router copied to clipboard

🗺 Pass a bag of props to `Component`

Open ryanflorence opened this issue 2 years ago • 6 comments

Discussed in https://github.com/remix-run/react-router/discussions/9687

  • Not just match but other stuff like navigate, location etc. (hash out what comes in there with the RFC)
  • Should be able to get full type safety since the loader/action etc. are all visible to the type system

ryanflorence avatar Jan 11 '23 19:01 ryanflorence

What can I do to move this forward? Are you open to PRs that implement this specifically?

dbartholomae avatar Feb 03 '23 08:02 dbartholomae

Do we still need this now that we're moving towards Component/ErrorBoundary instead of element/errorElement as of @brophdawg11's #10045?

MichaelDeBoey avatar Mar 06 '23 20:03 MichaelDeBoey

Based on what I see in the linked PR, I don't see a way to do something like

<Route path='/user/:userId' element={({userid}) => <UserProfile id={userid} />} />

that would have TypenScript error with Property 'userid' does not exist on type '{ userId: string; }'. How would this be achieved after the PR is merged?

dbartholomae avatar Mar 07 '23 02:03 dbartholomae

Initially implemented by #10045 with Component prop, though no values are passed to it yet.

ryanflorence avatar Mar 07 '23 19:03 ryanflorence

@ryanflorence If there is interest in something like this, I'm happy to provide a PR once #10045 is merged which either passes the params, or a bigger object containing the params to the component. I would suggest to only pass the params, as this leads to a really nice dev experience (see example below), and I also don't see any benefit for other parameters compared to just getting them from hooks, since the route params are the only ones where type safety increases. The main argument for passing in a more extensive object from my perspective would be to make it easier to transition from v5 to v6, or to keep the interface similar to loaders (which would mean putting the params into props.params).

Here's how I imagine the interface towards users of the library:

function UserProfile({userId}: {userId: string}) {
  return <>You are user {userId}</>
}

// This just works
<Route path='/user/:userId' Component={UserProfile} />

// This gives a TypeScript Error:
// Type '({ userId }: { userId: string; }) => Element' is not assignable to type 'ComponentType<{ userid: string; }>'.
//  Type '({ userId }: { userId: string; }) => Element' is not assignable to type 'FunctionComponent<{ userid: string; }>'.
//    Types of parameters '__0' and 'props' are incompatible.
//      Property 'userId' is missing in type '{ userid: string; }' but required in type '{ userId: string; }'
<Route path='/user/:userid' Component={UserProfile} />

dbartholomae avatar Mar 08 '23 07:03 dbartholomae

I love this @dbartholomae! I personally can't think of any reason why we would need other functionalities than the URL params and the integration with the components and their props would be amazing. Being able to pass a component as prop rather than a function might also be better for re-renderings since its reference wouldn't change. I would however still consider allowing a function to be passed as the prop value since as you said it would make it easier to transition from v5 to v6 🤔

fbarbare avatar Mar 16 '23 09:03 fbarbare