-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
[Bug]: useParams should not return undefined
#8498
Comments
You cannot know at compile time the component will be contained within any Route. Hence, the params must be partial. We have specifically chosen this type because anything else would encourage unsafe behavior and produce types that essentially lie to you. |
It's a route param - not query string. If the parameter doesn't exist it means the route is different. A common convention is that path/route params are manditory while query params are optional. |
I totally agree with @tzachov , this issue should be resolved instead of being closed. |
I agree with @tzachov. |
@timdorr I think that decision was completely wrong, #8498 (comment) already explained why. By default params must be mandatory. Let developer choose when to use optional params: const Post: React.FC = () => {
const params = useParams<{ groupId: string, postId?: string }>()
// expected: groupId is required and postId not
// actual: both are optional ...
/* ... */
} You make const Post: React.FC = () => {
const params = useParams() as { groupId: string, postId?: string }
/* ... */
} Why don't make
And in case of passing an object force devs that want old behavior to write UPD: didn't see #8200 (comment) and #8200 (comment) earlier, but that's exactly what I mean |
- make `type` of customSnippets typed. Previously it was a string, now it a string enum. Number support is preserved. - add `executeCommand` to allow running arbitrary commands on snippet accept - ### improve builtin `useParam` snippet: 1. Now it will appear on top with Event icon, similar to other builtin js snippets. Most importantly it now appear higher score than `useParams` 2. Now it will expand to `const params = useParams() as { groupId: string }` instead of `const params = useParams<'groupId'>()`. You can look at the [react-router issue](remix-run/react-router#8498) for the motivation of this change. You can use `useParamMode` setting to switch to old behavior. ---- - allow to use captured group names from regexs of `when` in `body` of snippet - ### Introduce New Type of Snippets! - ### Typing Snippets - More in readme feat: ### New builtin snippets - `ed` -> `export default` (for js langs) - New snippets for markdown: - `ts` -> `` ```ts\n$1\n``` `` - `ts` -> `` ```ts\n$1\n``` `` - `codeblock` -> `` ```$1\n$2\n``` `` (fenced codeblock) - `dropdown` (fenced codeblock) fix: Fix a rare case when the same snippet with multiple locations where included multiple times fix: Allow to disable sortText applied by default snippet config
I've found the most handy way for myself in using import invariant from 'tiny-invariant'
interface UserParams {
id: string
}
const UserPage = () => {
const { id } = useParams<UserParams>()
invariant(id, 'User id isn\'t set within the route')
// After `invariant` evaluation `id` considering as truthy
return <Profile userId={id} />
} |
Hello, I was wondering about why do we have to explicitly set I think that just casting it to our custom UserParams interface makes our code work propertly and also forces the return value to have the properties of the UserParams . Could you please explain? Maybe I am missing something. Thank you for your time, this is really important for me, I have been searching an answer for ages. |
My solution is just a custom hook. It's not perfect, but it works
Usage:
|
I agree, export const useRequiredParams = <T extends Record<string, unknown>>() => useParams() as T; |
how to pass an interface to a generic, an error pops up? |
I think this has to do with interfaces and Record, see this By the way, I have stopped using interfaces and now only uses types, but of course that is not always an option. |
Which version release has this problem solved? i am using 6.27.0 and issue is still there |
What version of React Router are you using?
6.1.1
Steps to Reproduce
Define a route with param (e.g.
user/:id
)Use
useParams
:This won't compile because
id
is possibly undefined andProfile
expectsstring
Expected Behavior
id
should not bestring | undefined
because/user
should match a different route than/user/123
Actual Behavior
id
isstring | undefined
unless you use cast:The text was updated successfully, but these errors were encountered: