Тёмный

Most React devs don’t understand generic components 

Matt Pocock
Подписаться 105 тыс.
Просмотров 49 тыс.
50% 1

Опубликовано:

 

26 сен 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 109   
@helleye311
@helleye311 8 месяцев назад
Absolutely love generic components. It's so nice to get all the highlighting. I usually extend {id: string}, this way I can add a key for mapping based on the id, and in most cases I have id in all the objects I'm displaying anyway. Another cool use case is a custom dropdown that takes a list of objects. Then you can also have a custom typesafe onChange. Also works great in combination with discriminated union props, if you pass 'multiple' prop your onChange is (value:T[])=>void, if you don't it's value:(T | undefined)=>void. It does get a little messy with so much functionality packed into one component (I also had a dropdown that would make a fetch call for data to populate it, which of course also was returning T[] for type safety), but I'm sure there's a way to make it more concise with some custom hooks and separate components.
@QwDragon
@QwDragon 8 месяцев назад
Completely agree!
@SpaghettiRealm
@SpaghettiRealm 8 месяцев назад
You can also extends object wich in js everything is object 😂
@JulianColeman03
@JulianColeman03 8 месяцев назад
I think more impressive than the explanation of generics was how you produced that intro zoom out effect by adjusting the focal length. Amazing
@JohnBuildWebsites
@JohnBuildWebsites 8 месяцев назад
THANK YOU! Was having that exact error when spreading a field object for a form today. Will try adding Extends Record to the type first thing tomorrow!
@JeyPeyy
@JeyPeyy 8 месяцев назад
Great video! The only change I'd make is to use unknown instead of any in TRow extends Record
@mattpocockuk
@mattpocockuk 8 месяцев назад
In this case because we REALLY can pass anything into that Record, it doesn't matter which one you pick.
@foolmoron
@foolmoron 8 месяцев назад
@@mattpocockuk I think the better answer here is that `any` is perfectly good to use in a generic type constraints, since the `any` is never used by an actual instance of a variable, it's just a constraint. If you were typing an actual obj variable whole values could be anything, you should really use Record, so that TS can encourage you to do the appropriate type narrowing or casting on the values that you get from that obj.
@barneylaurance1865
@barneylaurance1865 8 месяцев назад
@@mattpocockuk I'd think if they both work equally well then unknown is preferable. I avoid any as much as I can, I think of it as just a last resort escape-hatch for when you don't want or can't deal with static typing. It's weird blend of type type and bottom type at the same time.
@mattpocockuk
@mattpocockuk 8 месяцев назад
@@barneylaurance1865OK - but that rule of thumb doesn't make sense in a context where you want the widest type possible. In that case, either are fine.
@ColinRichardson
@ColinRichardson 8 месяцев назад
Such a Generic title
@tomasburian6550
@tomasburian6550 7 месяцев назад
Learned generics quite recently and love them. Great videos here, Matt. Subscribed for life.
@krauterfrischkase8939
@krauterfrischkase8939 8 месяцев назад
Wouldn't it be "more react" to render the list of rows outside the Table component and then insert that into the Table children? React's philosophy emphasizes composition over configuration which would make the Table component versatile and more flexible.
@proosee
@proosee 8 месяцев назад
I'm not an expert, but I don't think it is crime to have one component with two renderers instead of two components, especially if they never will be used separately, because how you want to use row without table?
@mattpocockuk
@mattpocockuk 8 месяцев назад
No, both ways are equally "React"
@ra2enjoyer708
@ra2enjoyer708 8 месяцев назад
It depends on the usecase. Especially in cases of tables, which have fixed structure declared by headers and can be expressed as 2D arrays easily, consuming JS types instead of opaque React components allows to wrap the results in row components with consistent styling. Versatility of children has a price on its parent in the form of forcing it to support a union of all children options. I.e. something like linebreaks for too long values in a column are trivially to compute from a string, which has a known length, while font size and all paddings are known to the table component, since these values are controlled by it in the first place. Interacting with them as components however devolves into hacks around React API and DOM-related boilerplate for counting pixels (good luck dealing with off-by-one errors caused by rounding errors).
@QwDragon
@QwDragon 8 месяцев назад
It's a simplified example. If he would've shown you smth real it would've take several hours to explain.
@Netherlands031
@Netherlands031 8 месяцев назад
Yeah but then the table can't for example do pagination, where the table keeps track of the page, slices the list of data and then only rendere that data with the render function
@pavloomelianchuk
@pavloomelianchuk 8 месяцев назад
Looks like another try for me, to understand "generics" in react. Eventually it will come 😜 Thanks!
@mycodingtutorials
@mycodingtutorials 8 месяцев назад
What font is this? What theme and what IDE?
@PickleRiiiiiiick
@PickleRiiiiiiick 7 месяцев назад
You're the best dude. And I follow you on everything.
@QwDragon
@QwDragon 8 месяцев назад
A very big problem with final code: using lambda fuction as a component will force recriating of everything it renders every time and will make completely impossible to keep any state anywhere inside. One more issue: no keys are specified on rows.
@sludgepuppy
@sludgepuppy 8 месяцев назад
Thank you, really nice and clear and simple 👍
@engine_man
@engine_man 8 месяцев назад
Dropping gems as usual. I never understood with that Intrinsic attributes thing meant.
@Clem.E
@Clem.E 7 месяцев назад
React Table nightmare now explained, thanks!
@henrym5034
@henrym5034 8 месяцев назад
Concise and to the point 👍🏼
@dmytroprokoptsov9587
@dmytroprokoptsov9587 8 месяцев назад
Hi, Matt) Your videos as beautiful as your accent! But I'm here to ask you and your community a question: is there a way in TypeScript I can check on type level whether object has keys or not? I know it is possible with Arrays, but with objects seems to be not
@JaffyMaglinte
@JaffyMaglinte 8 месяцев назад
Nice! Got it now
@thepetesmith
@thepetesmith 8 месяцев назад
I’m confused a bit because I always use React.FC and pass a props Type as the type arg. I don’t get how in your example you aren’t passing the type, but the generic infers the type by argument order? I’ve seen how you can pass a type argument in the jsx with angle brackets
@pedrohenriquepires9484
@pedrohenriquepires9484 8 месяцев назад
Wonderful content, as always! I wrote a small article on about this some time ago, inspired by your content about generics. Thank you for your amazing work!
@billyfigueroa1617
@billyfigueroa1617 7 месяцев назад
Matt your videos are amazing. I have learned a lot from you I do have a question. Is it possible to use different types for a generic component? for example, I have a carousel I want to create and I want it to be able to display different things. Like it can display an image and become a slider in a sense or it can just be a scrollable like hero section. Is it possible to have something like Carousel and Coraosel where Image and Info are objects that do not have the same attributes. Something like Image has name, urlImg and Info has header, subheader, content
@iamandrewluca
@iamandrewluca 8 месяцев назад
Another subjective opinion is using instead of props.renderRow(row) The former version allows to call hooks inside of it, but it looks strange. The benefit of the former is that you can pass a component renderRow={MyRowComponent} but you lose type inference. I suppose the latter is the right way of rendering the row in this case props.renderRow(row) Btw, great video as usual, short and on point!
@LetalisLatrodectus
@LetalisLatrodectus 2 месяца назад
Why use any in the Record instead of unknown?
@CodeZakk
@CodeZakk 8 месяцев назад
Yeah to the point and concise tutorial.my question is can we object and array on the extends and also is Record a typescript feature?🎉🎉
@andrewpleshko365
@andrewpleshko365 8 месяцев назад
Great! Thank you
@Rebel101
@Rebel101 7 месяцев назад
Hey Matt, question: See when you hover over react component jsx call, it just references type names instead of actual types like it does when you call is a a function. Is it possible to write a genetic type for ReactNode that solves this issue?
@dennisgonzales9521
@dennisgonzales9521 7 месяцев назад
2:38 addding a comma here throws me off, that why I prefer to use the classic function declaration for my components instead of arrow functions.
@ctpaintball4life
@ctpaintball4life 8 месяцев назад
Slotted components are really hot right now. Is it possible to do this type of inference with JSX?
@leotravel85
@leotravel85 8 месяцев назад
Record whould have been better
@QwDragon
@QwDragon 8 месяцев назад
No. Always use any instead of unknown in generic constraints.
@leotravel85
@leotravel85 8 месяцев назад
@@QwDragonWhy?
@fow7139
@fow7139 8 месяцев назад
@@QwDragon No, you should not. Any is not restricted and can be considered as a bad practice. In critical environments, it actually is. In those cases, you want to make another component from Table that will correctly wraps the type or pass it as a generic :
@Krzysiekoy
@Krzysiekoy 8 месяцев назад
How does typescript "decide" which prop to use for the type inference for the type argument T? Take this example: const Table = ({rows, randomProp}: {rows: T[], randomProp: T}) => { return rows } Table({rows: [1,2,3], randomProp: "foobar"}) This will error out saying "Type 'string' is not assignable to type 'number'." Okay, why does rows prop take precedence? Why doesn't this error the other way around, i.e. "Type 'number []' is not assignable to type string [ ]". What makes the "rows" component "win" when it comes to type inference?
@the_blue_flash
@the_blue_flash 8 месяцев назад
Have you tried switching rows and randomProp when calling the function? I think that's where it's inferencing. Another way would be specifying it (e.g. Table(/*args*/) )
@Krzysiekoy
@Krzysiekoy 8 месяцев назад
@@the_blue_flash Yes, I've tried switching the props around and it makes no difference.
@vytah
@vytah 8 месяцев назад
It doesn't matter except for the way the error message is formatted.
@mattpocockuk
@mattpocockuk 8 месяцев назад
Fabulous question. In your example, there is no true way to figure out which one goes first. So TypeScript picks one - I'm sure the compiler knows which, but I don't have an intuition for it. To customize which one gets selected, you can use NoInfer from ts-toolbelt. NoInfer will be coming to TypeScript in 5.4.
@Krzysiekoy
@Krzysiekoy 8 месяцев назад
@@mattpocockuk Thanks Matt! Appreciate your answer.
@versaleyoutubevanced8647
@versaleyoutubevanced8647 8 месяцев назад
do you have any thoughts on the fact we can't type children? ReactNode is more like Record for JSX I'm talking about complex children demanding like 3 childs, , and . Or restrict children to have only one child with data atribute 'foo'...
@andriiv7033
@andriiv7033 8 месяцев назад
Great. The only thing is that the any should be replaced with a generic type too, shouldn’t it?
@Shyam_Mahanta
@Shyam_Mahanta 8 месяцев назад
Where to buy typescript book you have behind?
@joshmarom
@joshmarom 8 месяцев назад
That was great thanks
@ninjarogue
@ninjarogue 8 месяцев назад
Excellent!
@yah3136
@yah3136 8 месяцев назад
I will just ignore this video and ask youtube to not show it again just for this nice presumptuous title ... well done Mr "better than most devs" ...
@mattpocockuk
@mattpocockuk 8 месяцев назад
It's just a shorthand for 'advanced content'.
@glorrin
@glorrin 8 месяцев назад
I have this problem in typescript I encounter from time to time, and no clue how to type it. function assignValue(myObject: TObject, key: TKey, value: Tvalue){...} TObject is usualy easy enough to type Tkey, is just keyof TObject But I have no clue how to get Tvalue to be typeof myObject[key]
@laminecherif7724
@laminecherif7724 8 месяцев назад
function assignValue(myObject:TObject, key:TKey, value :TObject[TKey]) {....}
@khoihoang8888
@khoihoang8888 8 месяцев назад
love it!
@MerthanMerter
@MerthanMerter 8 месяцев назад
amazing
@MaPhongBa129
@MaPhongBa129 8 месяцев назад
Put a comma after type param is magic, most of the time, I change function from arrow to normal function.
@hakuna_matata_hakuna
@hakuna_matata_hakuna 8 месяцев назад
can ytou do a video on extends , it seems like a super power
@gerhardsteenkamp562
@gerhardsteenkamp562 8 месяцев назад
The confusing bit for me was that it doesn’t work the way generics usually work, in that you don’t pass a type argument to the component, but instead the generic acts as a placeholder to infer the type of regular props that are passed to the component. And then you can use that inferred type in multiple places in the component.
@buggycoder7900
@buggycoder7900 8 месяцев назад
can't we have ??
@orcdev
@orcdev 8 месяцев назад
But what about my eslint rule "no any" 😅
@boris_raduloff
@boris_raduloff 8 месяцев назад
This is quite similar to lifetime annotations in rust but about types instead of memory freeing.
@mrlectus
@mrlectus 8 месяцев назад
no
@boris_raduloff
@boris_raduloff 8 месяцев назад
@@mrlectus extremely insightful
@macon5696
@macon5696 8 месяцев назад
some time ago, i've managed the same problem, but i did't find solution to do the same with memo without TS issues
@Wielorybkek
@Wielorybkek 8 месяцев назад
can't it be a footgun? whenever I see hacks like this I think that such use case was not considered by framework authors and they might not support it. it might stop working at some point or have bugs later along the way.
@mattpocockuk
@mattpocockuk 8 месяцев назад
No, it's not a footgun. It's an extremely common pattern used in tons of different libraries.
@1felixxex1
@1felixxex1 8 месяцев назад
nice
@saidabedi2836
@saidabedi2836 8 месяцев назад
🔥
@KoenVerheyen
@KoenVerheyen 8 месяцев назад
Don't need to add a key-attribute in this case?
@DemanaJaire
@DemanaJaire 8 месяцев назад
Still needed
@QwDragon
@QwDragon 8 месяцев назад
Yes, but that does nothing while he uses lambda function as a component...
@iMakeYoutubeConfused
@iMakeYoutubeConfused 8 месяцев назад
The only time I'm not guilty of
@michamazurkiewicz80
@michamazurkiewicz80 5 месяцев назад
Speaking from experience this is really bad to show to people. XD I have an app with 10 or more tables and initially someone had idea why not just making single table for all of them... But it doesnt really make sense cause each of these tables is different... has different actions, items, filters...etc... that we ended up with a monster that tides our entire application. Whenever you make change you have to go over entire app to check if everything is working etc. Lesson learned.. just copy the code and have 2 tables or 10 tables that are all simple and clean. Have logic only interesting for them and you dont have to worry to break entire app when making change in single table. So in this situation big no to generics.
@Hugos68
@Hugos68 8 месяцев назад
Congrats on becoming a father!
@akosbalint3485
@akosbalint3485 8 месяцев назад
Do somebody know how to add forwardRef to generic components?
@mattpocockuk
@mattpocockuk 8 месяцев назад
github.com/total-typescript/react-typescript-tutorial/blob/main/src/08-advanced-patterns/65-forward-ref-with-generics.explainer.1.tsx
@akosbalint3485
@akosbalint3485 8 месяцев назад
@@mattpocockuk Thank you Matt!
@lifeiscontent
@lifeiscontent 8 месяцев назад
Fix forwardRef so these kinds of components aren’t a nightmare to build
@kirylbehansky1315
@kirylbehansky1315 8 месяцев назад
Only react devs can’t understand that 😢
@paxdriver
@paxdriver 8 месяцев назад
I still don't understand the benefit of typescript. This is way more mental load than writing a proper function with guardrails. How is this easier than vanilla js?
@Netherlands031
@Netherlands031 8 месяцев назад
Because typescript will now error in the renderrow function if you try to access a row property that doesn't exist. And you get autocomplete if you do 'row.' inside of renderrow. So a much improved DX for the cost of just a few lines of code. The mental load is pretty small if you have some practice with this stuff
@deniyii
@deniyii 8 месяцев назад
It’s not supposed to be easier. It’s always going to be easier to write untyped spaghetti than any typed language.
@awekeningbro1207
@awekeningbro1207 8 месяцев назад
js is waking on sahara desert, ts is walking on a well built road on sahara
@paxdriver
@paxdriver 7 месяцев назад
@@Netherlands031 maybe i'll figure it out one day, just started with it this year and i've been writing js for over 20 yrs so it's probably a stubborn bias of mine, i'll admit. i'm trying to see it, though
@paxdriver
@paxdriver 7 месяцев назад
@@deniyii you can type javascript yourself if you write functions for it. that's my whole point. instead of focusing on all this new syntax and stuff it's cleaner code and easier to write when you yourself wrote the typechecking function. const kind of solved this for anyone who puts in a few minutes to write little type checking functions imho.
@fabius-maximus
@fabius-maximus 8 месяцев назад
Ugh vue does this way cleaner
@rafadydkiemmacha7543
@rafadydkiemmacha7543 Месяц назад
Is it me, or is VS Code generally quite terrible with React? I find myself fixing its bullshit autocompletion, indentation etc. all the time.
@badwolf9090
@badwolf9090 6 месяцев назад
They're not parentheses, we call them brackets in British English, don't let the Americans take over :-(
@echobucket
@echobucket 7 месяцев назад
If you would just stop making stupid const arrow functions and use the dang function keyword it wouldn't get confused about the type argument and you wouldn't have to use the comma.
@bhalsodbhavin9557
@bhalsodbhavin9557 8 месяцев назад
First view
@ColinRichardson
@ColinRichardson 8 месяцев назад
You managed to be the first view? Even though I commented a full minute before you? I am not sure that logic checks out.
@DemanaJaire
@DemanaJaire 8 месяцев назад
The fact that both of you even care.
@ColinRichardson
@ColinRichardson 8 месяцев назад
@@DemanaJaire I mean, I "could leave things being wrong".. But, then, we would still be going to libraries to get information instead of having the internet.. Progress and removing incorrect things must be done
@Keisuki
@Keisuki 8 месяцев назад
First reply
@macieja92
@macieja92 8 месяцев назад
Fuck me, hah I smiled when I realized that it's so freaking easy to understand while I've been having so many problems with understanding generics 😂
@AnthonyPaulT
@AnthonyPaulT 8 месяцев назад
can you do `extends object` instead?
@mattpocockuk
@mattpocockuk 8 месяцев назад
That's a bit looser, since arrays are also objects.
@GilEpshtain
@GilEpshtain 8 месяцев назад
the only downside is that you have to use the syntax "const C = (..." and cant write "const C: React.FC = ..."
@churraskindequeijo8418
@churraskindequeijo8418 8 месяцев назад
Nice
@syedhaider0916
@syedhaider0916 6 месяцев назад
Probably the best generic video ever.
@leftis95
@leftis95 8 месяцев назад
How come the comma "," solved the .tsx errors inside the generic type?
@Pete133
@Pete133 8 месяцев назад
Yes I would like to know why the comma makes a difference as well. Is it just a random buggy thing about typescript or are we missing something fundamental? *Edit* Ok so Matt says @2:40 that adding the comma lets typescript know that is a type parameter, but I didn't understand what else it would be other than a type parameter. Because we're using a const variables, which in a react app can be directly assigned to JSX... like const foo = ... typescript doesn't know that we're not trying to assign JSX. So adding a comma there lets typescript know we're using a type parameter rather than JSX.
@DmitriiBaranov-ib3kf
@DmitriiBaranov-ib3kf 8 месяцев назад
I prefer going with Record. And Vue 😅
@TeaBroski
@TeaBroski 8 месяцев назад
Wow, the knowledge this man ...spreads is always mind blowing
Далее
Infer is easier than you think
13:38
Просмотров 90 тыс.
Enums considered harmful
9:23
Просмотров 206 тыс.
Avaz Oxun - Yangisidan bor
14:29
Просмотров 244 тыс.
TypeScript Generics are EASY once you know this
22:21
Просмотров 137 тыс.
Finishing the Programming Language
12:44
Просмотров 506
Declaring globals isn't that hard
3:50
Просмотров 30 тыс.
Most TS devs don't understand 'satisfies'
4:10
Просмотров 56 тыс.
Generics: The most intimidating TypeScript feature
18:19
as const: the most underrated TypeScript feature
5:38
Просмотров 119 тыс.
Everyone's talking about gql.tada
5:06
Просмотров 43 тыс.
Projects Every Programmer Should Try
16:58
Просмотров 462 тыс.