Definitive Guide to React Component Design and the key to avoiding tech debt

  Рет қаралды 11,362

Kevin Ghadyani - JavaScript

Kevin Ghadyani - JavaScript

Күн бұрын

Instead of building up tons of tech debt with React, I'll teach you how to build better, more-flexible React components using "children-first" design principles! It's a combination of compound components (a lost art) and context.
Through years and years of coding day and night, I bring to you, a Definitive Guide to React Component Design; a set of skills and principles you could use for coding even outside of React.
Inspiration for this talk came from Ryan Florence's Compound Components talk: • Ryan Florence - Compou...
Ryan Florence's channel: / ryanflorence
Children-first components:
github.com/Sawtaytoes/childre...
This talk is about avoiding tech debt to make you a better developer.
Other similar terms are "React Clean Architecture", "React Design Patterns", "React Best Practices", and "Junior vs Senior code".

Пікірлер: 67
@mks-h
@mks-h 4 ай бұрын
I've been searching for content to improve my shitty React codebase, and out of about 10 way more popular videos, this is the first one with some actual content. Others just tell something basic without any convincing. But your video is so much better! A bit long, so I'll watch the rest later, plus I see you left long answers to comments, which I'll obv have to read now. But for now, thanks!
@KevinGhadyani
@KevinGhadyani 4 ай бұрын
Hope the rest helps you out! There are different ways to approach React components. I was aiming to fix tight coupling. In a later video I did with another group at Microsoft with a similar pattern, I also tried renderProps + useCallback, but it adds indirection. I use that pattern at my current job though. I came up with a way to do children-first with TypeScript and clever use of generics, but it requires some thought to figure out.
@dinoscheidt
@dinoscheidt Жыл бұрын
Amazing talk, could have used a bridge to the various styles of state managers (single store, local store), but enjoyed it a lot. Thank you for taking the time !
@SarShaGaming
@SarShaGaming 3 ай бұрын
This was AWESOME! thank you
@andreigatej6704
@andreigatej6704 2 жыл бұрын
Thank you very much for sharing this
@_va3y
@_va3y 2 жыл бұрын
I think the weakness of moving a lot of logic to context, is that it creates an implicit coupling to the component hierarchy. Context providers need to be always on top of context consumers. There can be a case, where you want to use a child component without a ctx provider, but it's not possible with this approach. This point is also mentioned in react docs about context Api, where they prioritise component composition over context api. Second, there there is an argument to be made about readability. With prop drilling, you are at least writing explicitly how data flows through the component hierarchy. I think excessive ctx api usage has a bigger potential to become spaghetti (that's a highly opinionated argument, but still). I personally come from Vue background and Vue also has its context Api alternative, called provide/inject. And it's *explicitly* meant to be used as an escape hatch, when you see it's the only solution possible. So I'm probably biased here. My solution would be something like this: 1. Hooks don't have that issue, so I personally try to use them over provider / consumer pattern. Composition > Inheritance 2. The 'children-first' approach you mention certainly solves half of the problems, and don't have any coupling between components + avoids props , so I'm 100% with you on that one. 3. In some cases, you need to specify, that some component needs to be above another one, like in the AccordionRoot / AccordionItem example. So here, the context api is certainly cool, because there's no way you'll put AccordionItem above AccordionRoot. To move explicit, I really like to use the compound pattern, where you'd write a component like this: foo So it's extra explicit about the fact that these two components belong together, and it'll probably break if you use one, without the other. It's also what tailwind uses in the headless ui a lot. In general, the cleanness of code is in the eyes of the beholder often, and the number 1 thing we all try to avoid is 50+ props drilling 6 levels deep. And the difference of HOW to do that can be often a thing of preference
@KevinGhadyani
@KevinGhadyani 2 жыл бұрын
I really appreciate you watching my talk and spending the time you did to write a thorough response. # 1 To your first point, the context logic I'm proposing is only for logic components, not UI. This way, you don't run into situations where you can't compose those components using props. They also logically belong together, so the coupling there makes sense; although, you can always switch out a context consumer (like `VisibilityTarget`) with one of your own. I had to write my own component for OneForm by pulling in the `useField` hook before. I needed it for a weird situation relating to a component. Exposing that hook was meant to be clutch and only used when absolutely necessary. For everything else, the `translateProps` function sufficed. # 2 You can assign a default value to `createContext`. I always do this because I often render context consumers in Storybook and don't want to mock every context. These days, I'd prefer context be limited to logic components. With `cloneElement`, your consumers can then rely on props (as you're suggesting), but then `cloneElement` allows the medium-coupled context consumers to associated with the provider: ``` {/* props component */} ``` # 3 I completely agree that improper use of context, like you'd have with `$rootScope` or any `Provider` variant in AngularJS, can easily lead to jQuery-like code. That's why separation of concerns is so important. The point is not to simply use context, but to create building blocks with contracts, so you don't run into those situations. # 4 I'm not familiar with Vue, but I looked up the docs on `provide` and `inject` (vuejs.org/guide/components/provide-inject.html). I wouldn't see this as an escape hatch personally. Context is old-hat for me. When I did React prior to hooks and Context API, I'd write only stateless function components. Redux was the only way I had state. I'd wrap my simple reducers in a higher-order reducer that segmented state based on a `name` prop. When selecting from Redux state, I could observe only that `name` and when dispatching actions, I could also specify the name. Because it's based on the component hierarchy, React's Context API allows you to avoid the explicit `name` prop unless you need an escape hatch. It's actually a benefit and only possible with composition. # 5 I don't agree that hooks -> composition | context -> inheritance. Context is optional dependency injection. The is the opposite of inheritance. Another limitation of inheritance is only having one explicit parent. You can have multiple contexts in any given component; therefore, it's composable. # 6 I'm fine with you putting `Accordion.Root` etc. I don't do that for my slides because it's too confusing, and every character counts. I looked up headless UI and Tailwind (tailwindcss.com/blog/headless-ui-v1). This is definitely a similar pattern as you suggest. I also like being explicit. Two component libraries I worked on were setup with the object `.` pattern because exports were easier. I'm not opposed to it, but it doesn't allow for tree-shaking. I do like knowing component X and Y belong together, but that's not available on every project, so I typically use prefix namespacing instead: `AccordionRoot`, `AccordionItems`, etc. # 7 You pointed out a flaw in my design without realizing it. "there's no way you'll put AccordionItem above AccordionRoot" I've seen an accordion in an accordion on government websites. While it's bad UX, it's still something that could happen in other cases. But I thought about this more and realized you found a flaw in my design: ``` {/* this is an issue */} ``` It made me realize that putting a top-level provider means there's no way for it to provide that context 1-level deep; although, I FOUND A SOLUTION! You can provide 2 contexts in VisibilityProvider: ``` {/* uses default */} {children} ``` By doing it this way, you can shut-off the parent `VisibilityControlContext`. Sadly, this only works if it's in another `VisiblityProvider`. It won't work if you're outside of it; although, why would you be? You could create a ``; although, I don't think you should ever be getting into this situation. It's some serious code smell :p. # 8 From reading your response, I realized it might be valuable to have components able to be controlled by both props _and_ context. While you'd accept values through context, you also be able to override those with props as needed. I've built this style before when I had to support both a new (context) and old (props) API at the same time in a component library. I think this is a bit over-engineering to do it on every component unless you could find a need where it made sense. # 9 I wonder how you avoid 50+ props drilling if you don't have a pattern of principle of using context and being children-first. I've never come across an app dependent on props where that wasn't the case. The majority of apps use Redux or only context providers at the root. After the first time I presented this talk in person, people came up to me saying "I never thought I could use context like this". That was the most common feedback I'd received. # Conclusion Thank you so much for your detailed response! I love getting feedback on my talks, and you really had me thinking hard for a solution to the
@kishoreandra
@kishoreandra 2 жыл бұрын
Amazing Kevin 🙌
@keelangibb565
@keelangibb565 3 ай бұрын
Hey man this is a gold mine of information. Keep it up. You should do more videos in this style with the slides. The way I learn most is when I get a short explanation of what a library/concept is first, why you need it, and why you should care. Then I like seeing an actual concrete example of how things are done using framework/example A and how the equivalent thing is done in framework/example B. Then I have the full context and can actually understand how example B solves the problems in example A and why I should even care in the first place. (think class + lifecycle vs function + hooks). This way you can gradually build on example A and B as you continue through the video and you can also isolate sections of code from example A, B or even C without needing to give full context of each to get your point across. I think this way is pretty digestible for most people and it makes sure the viewer is not lost in the middle of an explanation and they can discover why something is so elegant themselves. Anyways, liked and subbed hope to see more soon.
@KevinGhadyani
@KevinGhadyani 3 ай бұрын
Thanks so much! I'd love to do more of these. I even have one ready on TypeScript but haven't had time to put it up yet (3 kids now) These styles of video take two weeks to create including all weekend and also time practicing my ad libs. Really glad you like the production value!
@keelangibb565
@keelangibb565 3 ай бұрын
@@KevinGhadyani Yeah no worries I know it can get chaotic. I do have a few questions though. 1. What’s your stance on server components? Does this model still work with all the context? I’m assuming a lot of them would need to be client components to work to track the state. 2. You briefly mentioned jotai. Could you use it instead of context? 3. Opinion on tailwind now that it has exploded in popularity. I’ve personally used it for a few years now and couldn’t imagine styling an app without it or a solution very similar it. Shadcn/ui which runs on radix is also incredible to use and it looks like it uses a similar pattern you describe in the video. Would you call that children first?
@KevinGhadyani
@KevinGhadyani 3 ай бұрын
​@@keelangibb565 For #1, server components can track state too. The server keeps the HTML loading in the background and throws JS it generates at the client. That's how it works. So if you have state, it should retain in server components. Am I missing something? That's what my original exploration showed when I first tested it out in a different video: kzfaq.info/get/bejne/bLiPpZly1tnHoYU.html&pp=ygUbcmVhY3QgMTggc3NyIGtldmluIGdoYWR5YW5p #2 YES! I've actually used Jotai 4 times now in place of context. If I need global context, I use Jotai. It's like Redux in that it's not tied to React, so you can use it to write your own logic and associate multiple frameworks or multiple React instances. This is very common with micro frontends. #3 My opinion on Tailwind hasn't changed except on one point (I'll say at the end). If you write your HTML with Tailwind classes, you're doing it wrong. You need to write Tailwind like you're writing Emotion CSS (which you shouldn't be writing inline if you want your render code to be readable). Make it type-safe (which is super difficult to do in VSCode when it's not inline) and add some helper functions so it's easy to do line-by-line (function args) rather than a stupidly long string of random classes. There are so many gotchas! Vanilla Tailwind sucks and leads to the same problems I dealt with at a marketing site job in 2012 where you literally couldn't tell what was going on with the CSS or the HTML. YUCK! I absolutely don't recommend it if you're writing HTML like it's 1994. Also, unless you're using Vite, it's tricky to get Tailwind setup correctly. You have to purge out classnames from the final compiled output or your bundle jumps up 4MB. Lastly, you cannot use Tailwind classnames. This is why you _need_ helper functions or something similar. Tailwind classnames have to be namespaced you absolutely will run into the same Global CSS issue everyone runs into when you try to scale your site or upgrade something (like the Tailwind version) or change one style in one place of the Tailwind config and hope it doesn't globally affect your whole app. I am constantly dealing with micro frontends, and all of those have different CSS considerations based on the version of the component library they're running. If Tailwind isn't namespaced, they'll all share the same Global CSS, so when certain micro apps appear on the page at the same time, it could lead to different outcomes depending on which are loading when. Good luck debugging that! It will take WEEKS. And the problems will change over time as different apps add changes. So in conclusion, yes, you can use Tailwind, but I think you need to do a lot of work to make it feasible. I would absolutely never use it out-of-the-box. And so you know, I've done 2 Tailwind projects so far successfully on side jobs, so I'm speaking from experience.
@lightyagami5963
@lightyagami5963 2 жыл бұрын
Awesome! Worth watching over and over again. Would be even better if having subtitles.
@KevinGhadyani
@KevinGhadyani 2 жыл бұрын
I have a mostly-perfect script from a transcription app I use. If you wanna edit the script and fix the weird stuff, I can add it to the KZfaq video. I'll even pay you for your time 👍.
@isoldpower
@isoldpower Ай бұрын
@@KevinGhadyani I can write Russian and English subtitles for you. Are you still interested?
@KevinGhadyani
@KevinGhadyani Ай бұрын
That's awesome! How would you add them?
@mashab9129
@mashab9129 Ай бұрын
great talk! 🔥
@eukursg
@eukursg 3 ай бұрын
IMHO the technical part of explaining what is props and children was good. The part that's crazy to me is the obsession to make things more complicated that it needs to be. The take in this video is that you should take the responsibility that the other devs gonna produce bad code and the solution is to write a complex and difficult to read code to mitigate it.
@KevinGhadyani
@KevinGhadyani 3 ай бұрын
I'm not exactly sure I understand your point, but I'll respond the best I can :). I take a different approach at each company I go to based on the needs of the org and the existing codebase. This is just one solution you can use to solve the problem of tight coupling, but not something that works everywhere you go. In general though, the more complex your library, the less complex the code consumers need when consuming it. Where I work now, I have a different approach than this video. Instead of component usage freedom, they want API stability and ease-of-use. Now we're creating one component for each feature rather than a bunch of them that you assemble because that follows the design system better (unlike the patterns I had at this other company). It's a 180 degree difference in component design. The goal of TypeScript and other coding patterns is to make it dead simple to write code the intended way, so other devs can't screw it up.
@pawekoaczynski4505
@pawekoaczynski4505 Жыл бұрын
Hey, I've enjoyed the talk, especially until 20:00. The thing about your children first design is that it's very different from what we (as frontend devs) are used to. The problem with that is that it would be hard to get others to do it. And most importantly - they might not understand it. They might completely butcher a completely fine and reusable component. This is what I'm worried about with this approach. I've seen trunk based development and functional programming - two very good approaches in my opinion - ruin a workflow or a code, because of one or two people who didn't know what they were doing. And that's not because they were a new programmer, it's just that they were not used to the nuanses in a codebase. Again, I loved the talk, and I don't want to sound overly negative. I might give it a try, but it's possible that I will go with a more common approach c:
@KevinGhadyani
@KevinGhadyani Жыл бұрын
That's great feedback, and you're exactly right! You build tools for the people using them. I often go out of my way to pull people into best practices, but different companies have different needs. Where I'm working today, we had 1K devs rather than 50, so my ability to educate is severely limited. I heavily rely on TypeScript to enforce our intent, and really really lock down our props because long-term stability is key. They don't want people deviating, so I'm not using Children-first; although, internally, I use a renderProps inner wrapper variant with useCallback to maintain memoization. It still has passthrough props, but it fits the needs of this org. TypeScript helps a ton! I was all-JS when I originally did this talk.
@heroe1486
@heroe1486 2 жыл бұрын
Thanks a lot for this, as a beginner/intermediate software developer this kind of content that goes beyond usual KZfaq's material is really valuable to level up. I went ahead on my editor to try to implement the child first pattern with cloneElem and Context but if I may suggest something I think that this format suits well for conferences but a slightly more decoupled format within several videos with executed code examples to compare the different approaches might suits KZfaq better and be more accessible.
@KevinGhadyani
@KevinGhadyani 2 жыл бұрын
I appreciate your feedback. What might solve your problem is chapter markers. If I did break this up, I don't think anyone's gonna watch the other parts. Also, the presentation doesn't make sense without the context of the full talk. If I split these up, I'd have to re-explain why tight coupling is bad and tech debt in each part. I've also seen other KZfaqrs more successful from uploading longer videos. I've also heard that multi-part videos are a "bad practice" on KZfaq.
@heroe1486
@heroe1486 2 жыл бұрын
@@KevinGhadyani Maybe making a playlist + just specifying at the beginning of each part that it only makes sens if you've watched previous videos. That way you could have more in details parts while still managing to not have a several hours monolith videos. For the format maybe you're right, I often got confused because short videos in form of series (see for example code evolution) are successful in general but it's true that the first video of the serie might have 10 to 100 times more views than the last one but I guess that's inevitable, people get excited at the beginning but then quickly give up. In the other hand there are 10 hours tutorial videos that got a massive amount of views, but at the end how long people watch them ? I don't have the stats but if it follows the previous pattern I'm confident people just watch few minutes. It feels like people see them as "a full course" and just jump into them. Don't know if you know Jack Herrington ? He makes videos about JS/TS and for me he nailed the perfect balance
@thorw2136
@thorw2136 3 ай бұрын
I think chapters within long video is more that sufficient to keep track of last watched part. Keep it up. I Liked the video 👍
@wvovaw3052
@wvovaw3052 3 ай бұрын
This is what real HTML programming looks like!
@pranavdhamanage
@pranavdhamanage 2 ай бұрын
I love the way you have dived deep into design patterns, but one main thing I am unsure about is that in the docs react team has mentioned not to use cloneElement and they have deprecated the api as well . So what’s your take on that? Would love to hear
@KevinGhadyani
@KevinGhadyani 2 ай бұрын
The React team doesn't necessarily support all use cases, but many libraries use `cloneElement` internally. I've been looking at alternatives for a while now because I never liked how this was invisible and difficult to enforce in TypeScript. On the other hand, I figured out how to make render props fit my needs with memoization. Months later, in an interview with a Microsoft dev, he pointed out I could use useCallback and get a similar effect! It's not exactly the same, but it fixes my biggest gripe of render props. Another friend pointed out you could wrap these component functions to create new ones that had the functionality you wanted built-in. Where I work right now, they wanted render props with useCallback, so that's what I have. I haven't experimented with new ways to fix this since, but I'm sure there will be better ways in the future.
@user-ru8hn9hb5c
@user-ru8hn9hb5c 4 ай бұрын
First 10 minutes: never heard components explained better
@KevinGhadyani
@KevinGhadyani 4 ай бұрын
Man, that's great to hear thanks! ;)
@AlphaHydrae
@AlphaHydrae 2 ай бұрын
This is great, what I don't quite get is how does the make the inside it trigger the event needed for the logic of the modal? Does it clone the child with an extra onClick prop inserted somehow?
@KevinGhadyani
@KevinGhadyani 2 ай бұрын
Exactly!
@dealloc
@dealloc Жыл бұрын
Your example of Accordion could be simplified by using data- and ARIA attributes to annotate your components and make them semantically correct, make them stylable and easy to test. The component itself doesn't need to know any styling, except for maybe orientation, which also can affect behaviour. There's no need for cloneElement here, so implementation is simpler, too. ARIA attributes are often missed. By themselves ul and li does not represent an accordion, it represents a bullet point list semantically. Accordion, as the name suggests, visually collapse and expand sections. Sections have headings and a body, which does not fit the semantics of unordered lists, which are typically just content. You may as well use divs and ARIA attributes to properly specify state, labels and roles for the content. Using ARIA labels to annotate the behaviour and state of a component is important for accessibility. Additionally you can select those ARIA attributes in CSS based on the state, for free. Data attributes are useful to give meaning to the component outside of it and without leaking abstractions. It makes your components simpler to use, more accessible and makes it easily testable in E2E tests without leaking implementation details. It's all in the DOM.
@KevinGhadyani
@KevinGhadyani Жыл бұрын
I think I'm understanding you correctly. But the examples I gave had a single Accordion component that took an isVisible prop and that's it. All the visibility logic is handled in separate components. But handling the complex aria associations are automatically handled by the logic components and passed into the accordion. A list of accordions would be wrapped by a ul and a bunch of li right? Did I say something counter to your comment?
@KevinGhadyani
@KevinGhadyani Жыл бұрын
This is the implementation from the presentation. I think that'll explain it more: github.com/Sawtaytoes/children-first-components/tree/master/src I'm changing this API in the future for TypeScript awareness using the builder pattern (TypeScript-first shown in another video of mine), but the new API will still retain almost all principles of children-first design except one thing: plug 'n play convenience. You get a bit of optional boilerplate for the benefit of better type documentation and a complete avoidance of cloneElement. This was brought up because cloneElement is seen negatively by React devs and doesn't even work in Solid.js without major compromises. The new pattern will be more universal.
@dealloc
@dealloc Жыл бұрын
@@KevinGhadyani I was thinking of doing it a bit differently without the need for cloneElement; For example, in case of Radix UI, it accepts the state (either controlled or uncontrolled, based on `default*` prefix) and a event listener in the root component. This way it can pass that state through to the child components that observes from the same context. This also makes it easier to hook up state, without the need to add conditions inside your component, but just by passing state and some dispatch in the root. The AccordionItem doesn't make much sense without its root anyway, neither does the AccordionTrigger or AccordionContent outside of the item-they are naturally coupled (compound). This could also apply to your generic Visibility component. The user's own content is wrapped by these outer components anyway, so you already have all the power without the need to clone.
@Nicopellerin
@Nicopellerin Жыл бұрын
Great talk! but if you're not going to show the code for a lot of these examples, I think a link to a github repo would be helpful
@KevinGhadyani
@KevinGhadyani Жыл бұрын
I built a library out of these logic components, but I haven't published it yet. You can find them here: github.com/Sawtaytoes/children-first-components/tree/master/src
@Nicopellerin
@Nicopellerin Жыл бұрын
@@KevinGhadyani thanks!
@wesleynewcomb
@wesleynewcomb 2 жыл бұрын
I'm still digesting this. I think in general I agree with a lot. I'm the one making the stink of using good patterns and avoiding tech debt at my company. A lot of my coworkers can see tech debt after the fact, but they can't see the actual cause. It's usually just, "we couldn't predict that this is what we'd have to do." Sure, that's true in some cases, but you can still maintain a lot of flexibility. And this talk showcases that with your building blocks concept. cloneElement frankly scares me lol. I think its biggest strength is also its biggest weakness: that to the consumer, it's "magic" that "just works." I agree that I shouldn't care *how* something I'm using works, just how *I* need to use it. I think I get how you're using it here though. At first I thought you were doing the compound component pattern with that, but it seems you're doing that with context where appropriate. There are certainly situations where there could be another layer between a parent part of a compound component and a child part. But using components that clone their children to inject props is certainly interesting. It's like a more declarative HOC that can also be used inline. I know you don't use Typescript, but I'm curious if there's a way to type this. Probably is. Like "I need an instance of a component that could take this prop." I think it'd be something like ReactElement void }>. As someone else mentioned, I would also like to see examples with more depth. I don't know if you could write up a gist or something. I know coming up with examples that imitate real world use cases can be difficult, but with the video format and the slides only containing so much information, it's hard to keep a mental image of what the code might look like.
@KevinGhadyani
@KevinGhadyani 2 жыл бұрын
Thanks for your response! You're totally about people not seeing the cause of tech debt. I've also worked at numerous places where they _always_ say they couldn't have known, but the design was such that it was absolutely gong to cause it. # 1 `cloneElement` was also scary to me when I first used it. I tried it once on a `Button` where they would pass in an `` component, the only one we accepted, and I modified the icon with the correct `size` relative to the button. This is tight coupling but also my first time using it. # 2 You're right to point out this isn't regular compound components; context is key. cloneElement is only used for the presentational UI components. The logic itself is tucked away in context. Glad to hear you understood this deeply! 👍 # 3 I like the idea of relating it to higher-order components. Standard `withTheme` and `connect` hocs are static, but render props is a dynamic version which is why you can replace `connect` with `` (github.com/reduxjs/react-redux/issues/920). To remove boilerplate and get the same effect with standard React, cloneElement is the dynamic equivalent. # 4 I personally don't use TypeScript on home projects (at least not yet) and definitely not for presentations since I wanna keep things simple. On the other hand, I'm forced to use TypeScript at my new job, so I've been learning it since March. I was also thinking of somehow modifying `children: ReactElement`. If you figure out a way, please tell me, and I'll put up a video on it. I can even Zoom call you in the video since you'd be the one who solved it. I haven't had to solve this at work just yet, but I will later this week. # 5 You're correct about the slides being limited. I focused on the API and not the implementation for that reason. It's also a limitation of what people wanna watch on KZfaq. I even moved all my live-coding videos to a separate channel because they were killing this one. I have an implementation of Picker available on CodeSandbox: codesandbox.io/s/picker-component-architecture-tq0jk?file=/src/Picker.jsx. The Visibility components I've written for companies, so I don't have any available on CodeSandbox. I was honestly thinking of building a library instead. It's not like this couldn't be open source. It's literally the simplest set of building blocks that you'd use 100 times in your apps. Problem is that building a library would take my free time, and I get paid to do it at work 🤷‍♂️.
@wesleynewcomb
@wesleynewcomb 2 жыл бұрын
@@KevinGhadyani I think the difficulty with typing it is going to be for components that need the prop that is being injected by the parent when it's cloned. TS doesn't know that the cloning is happening. Now, you could make the prop always optional, which is kind of fitting (a button doesn't *need* onClick technically) but this doesn't seem like a solution that works universally.
@KevinGhadyani
@KevinGhadyani 2 жыл бұрын
Actually, it should be optional. Why is onClick required? What if you're testing the button's text? Why tightly couple the onClick mock in that test? I actually advocate optional props with sane defaults normally anyway. Existing props will need to be mocked when writing regular code or the cloning won't work Like with TypeScript vs JS, optional props are a different mindset.
@KevinGhadyani
@KevinGhadyani 2 жыл бұрын
What's upsetting to me is realizing I missed that. When I did this in person, someone asked, so I answered it. I have plans to do a short video in the future on "sane defaults", my own term.
@wesleynewcomb
@wesleynewcomb 2 жыл бұрын
@@KevinGhadyani We may just disagree on this, but for me, sometimes a "sane default" is to throw an error. For example, you have these parent-child relationships with these compound components that utilize context. In the example code you shared in this thread, you default the context value to the same shape as you'd expect (which certainly is useful for inline documentation) with empty values. For situations like that, I tend to leave the default context value as undefined. Then in the consuming child component, I throw a descriptive error if the context's value is undefined, saying that the context provider with a valid value was expected to exist. If I provide type-compliant defaults, I'm left with situations where it could silently fail if someone forgot to use the parent component. Then that's extra time spent debugging for a pretty simple bug with a simple solution. Is there something I'm missing about providing these default empty values?
@bart9522
@bart9522 2 жыл бұрын
Very interesting video. But the code snippets are quite hard to follow without full code samples.
@KevinGhadyani
@KevinGhadyani 2 жыл бұрын
What specifically do you want to see on slides? I tried removing cruft so there's less code to read for the 2-5 seconds it's on screen. Are you wanting to see the implementation or do I need more code in the slide? Does this help? github.com/Sawtaytoes/children-first-components/tree/master/src Go to Visibility or Picker stories to see uses.
@bart9522
@bart9522 2 жыл бұрын
@@KevinGhadyani Yeah that helps a lot! 👍 I'll dig through it and see if I can understand everything. It was hard for me to understand how the 'children-first' approach without seeing the actual implementation of all the pieces. Part of the reason is probably that I'm not super familiar with advanced React concepts yet. For me personally, especially if it's a video, I like to see complete examples, I can pause if I need some more time.
@damilare1982
@damilare1982 2 жыл бұрын
@49:37 Is sooo true 😅😅😅
@tombyrer1808
@tombyrer1808 2 жыл бұрын
Link for 1 form plz?
@KevinGhadyani
@KevinGhadyani 2 жыл бұрын
docs.oneform.dev I know, it doesn't show up easily in Google searches. No clue why not.
@PS-dp8yg
@PS-dp8yg 7 ай бұрын
Kevin, are you going to create a course on this subject? I'm interested and don't mind helping a fellow coder by paying for a course design by you..
@KevinGhadyani
@KevinGhadyani 7 ай бұрын
I appreciate it! I'd love to make a course especially with the passive income source. Of the few courses I've tried for work, I've never gotten anything out of them, and I've never finished any either. I don't really think I'm qualified to do courses. I'd hope my KZfaq videos provide enough information.
@PS-dp8yg
@PS-dp8yg 7 ай бұрын
@@KevinGhadyani Bummer... A course on how to properly design components would be awesome. Anyway, do you have source code with all the examples above? I would like to look at them in order to learn more. Some of the stuff is just too vague. BTW, I'm pretty sure you are qualified. :D
@DarrylHebbes
@DarrylHebbes 3 ай бұрын
I think I am fairly smart but I had to watch this twice to grasp the concept, and that is with 8 years React experience, I tried slowing it down to 0.75 speed but it makes you sound drunk... lol. Thanks though... I am sure after a good nights rest it will make sense. I am always bemoaning counter increment examples, now I wish there was one. Perhaps I will just try it out myself.
@NikhilKesari
@NikhilKesari Жыл бұрын
Kindly write a book on this
@KevinGhadyani
@KevinGhadyani Жыл бұрын
Get me in touch with a publisher ;p
@monarchgam3r
@monarchgam3r 4 ай бұрын
wish there was more source code for some of this
@KevinGhadyani
@KevinGhadyani 4 ай бұрын
I have it linked in the description I thought. Are you looking for something else?
@damilare1982
@damilare1982 2 жыл бұрын
Am I wrong 🤔 I feel like building components like this is mostly suitable in vue than in react where one could easily register the library globally and use anywhere without having to import stuffs . Cause imagine creating a sign up form, a Modal, a drop down in a single page , you would have to import a lot of things, import this import that ooh God 🤣 this is interesting
@KevinGhadyani
@KevinGhadyani 2 жыл бұрын
I think it's fine. I often import a bunch of stuff. Never used Vue, but if you've seen the popular UI library Material-UI, they also make you import a bunch. From using OneForm and these other methods, you get used to it. It makes the DOM behavior very clean.
@bart9522
@bart9522 2 жыл бұрын
Fourty hour days?!
@KevinGhadyani
@KevinGhadyani 2 жыл бұрын
Back when I was working on the game, I was doing a lot of stuff all by myself, but I was a junior-level dev. I'd sleep once every 2 days sometimes. It wasn't every day each week, but it was quite often. I remember being up for so long my vision would get blurry. I slept when people stopped having things for me to review, but because everyone was global, I was up around the clock.
@JLarky
@JLarky 2 жыл бұрын
Stop yelling at me 😅 I will fix it eventually
Speeding up JavaScript Arrays with Transducers. RxJS vs Ramda vs Lodash #KCDC21
54:53
Kevin Ghadyani - JavaScript
Рет қаралды 3,2 М.
WHO DO I LOVE MOST?
00:22
dednahype
Рет қаралды 26 МЛН
Which one is the best? #katebrush #shorts
00:12
Kate Brush
Рет қаралды 20 МЛН
Stupid Barry Find Mellstroy in Escape From Prison Challenge
00:29
Garri Creative
Рет қаралды 8 МЛН
Each found a feeling.#Short #Officer Rabbit #angel
00:17
兔子警官
Рет қаралды 7 МЛН
10 React Antipatterns to Avoid - Code This, Not That!
8:55
Fireship
Рет қаралды 714 М.
Every React Concept Explained in 12 Minutes
11:53
Code Bootcamp
Рет қаралды 395 М.
Design patterns in React
14:37
Cosden Solutions
Рет қаралды 143 М.
Un-Suck Your React Components - Composable & Compound Components
15:47
Why Signals Are Better Than React Hooks
16:30
Web Dev Simplified
Рет қаралды 453 М.
3 Beginner React Mistakes That Can Ruin Your App
20:19
Web Dev Simplified
Рет қаралды 101 М.
Refactoring a React component - Design Patterns
15:19
Cosden Solutions
Рет қаралды 90 М.
React Like a Pro: React Best Practices
9:55
PedroTech
Рет қаралды 8 М.
This is the Only Right Way to Write React clean-code - SOLID
18:23
WHO DO I LOVE MOST?
00:22
dednahype
Рет қаралды 26 МЛН