
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
In this video, the presenter introduces a starter repo for a React application and encourages viewers to follow along or simply watch. They discuss React patterns such as higher order components, compound components, provider pattern, function as children, and portals. The focus is on writing clean and maintainable code in React to make projects easier to scale, fix, and understand. The presenter, Adrian, founder of JavaScript Mastery, shares their experience and upcoming projects. The goal is to simplify React patterns and help developers improve their coding practices. The video aims to educate viewers on utilizing React patterns for modular and maintainable code.
How do I remove the blur effect from my CSS?
I removed but the blur is still there. Any ideas?
filter: blur(5px);
Does work for removing blur from modals?
backdrop-filter: none;
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:00 Let's get started.
00:00:02 Before I start with the presentation, I will share a starter repo in case you want to follow along right here to the chat.
00:00:09 So you can quickly clone it, fork it, download it, whatever you want.
00:00:13 run MPMI and then MPM run dev to quickly spin up your starter react-v application.
00:00:20 It's nothing special, just some basic boilerplate code with a couple of routes that I have prepared containing different react patterns.
00:00:27 But I would even advise that if you're just going through this workshop for the first time live with me, you don't necessarily even have to code along.
00:00:37 You can You can just watch and then download the starter later on, or even download the final repo, which I will also drop in the chat right here.
00:00:46 So there is this starter repo, which I will open up on my screen right now.
00:00:52 It's this one right here.
00:00:53 And there's also the final code base.
00:00:56 So if you're a bit more in the senior or mid side, you might not even have to follow along.
00:01:00 Rather, I'd want you to just pay your attention to this workshop.
00:01:04 And then later on, you can just go through the final repo on your own.
00:01:08 So I will drop that into the chat as well.
00:01:11 What you'll be able to see once you actually run it is something looking like this.
00:01:15 It is a simple page consisting of a couple of links pointing to different routes.
00:01:22 And each one of these routes is pointing to a different React pattern.
00:01:29 Again, we're starting with higher order components, as you can see here.
00:01:34 And some people are saying that it is blurry.
00:01:36 So if it is blurry, thank you, Florian, for mentioning that.
00:01:39 I'll find a different way to share my screen.
00:01:42 I appreciate it so much that you shared it right here.
00:01:45 Today, we're going to be talking about React patterns, and I'll try to simplify them.
00:01:49 I'm Adrian, and I'm the founder and lead educator at JavaScript Mastery.
00:01:55 Some of you might have seen it on YouTube.
00:01:57 We just recently crossed a million subscribers, which was a big milestone.
00:02:03 And we are also working on a coding platform called jsmastery.pro, where we're trying to find some very new ways of teaching people how they can code through
00:02:14 MDX lesson and live examples of these patterns, for example, they directly within the editor.
00:02:19 But that's a topic for another day.
00:02:22 Today, I will try to help you write clean and maintainable code to help you make your React code a bit less of a mess because we're all aware that sometimes
00:02:33 big code bases can get messy and no worries there.
00:02:38 In today's world, developers are focused on writing clean and maintainable code.
00:02:43 And we're all aiming for those projects that are easy to scale, fix, and understand.
00:02:50 And React gives us some great patterns to help with that.
00:02:55 But they can feel a bit tricky if you don't know where to start.
00:03:00 So today, you will learn interesting React patterns that promote modular and maintainable code.
00:03:09 React is all about components, right?
00:03:12 We'll talk about higher order components.
00:03:15 Yep, you guys called it.
00:03:16 Compound components, provider pattern, function as children, portals, and I'll provide all these with real world examples to make it click.
00:03:29 So as I said, I've prepared a starter repo with common coding scenarios that we typically encounter in real life.
00:03:37 And then we'll take each one of these examples and apply a pattern to it, just to show you how much easier and better life can get by using them.
00:03:46 How will these patterns actually help you?
00:03:49 Well, they will help you to learn to write cleaner and easier to read code.
00:03:56 They will help you to improve your team collaboration with consistent patterns.
00:04:01 They will make your apps more scalable and easier to maintain.
00:04:05 And they'll give you the confidence to tackle complex problems because you'll know how to approach them from some pre-existing angles.
00:04:13 So without wasting any more time, let's explore these patterns in depth.
00:04:19 But just for a second, let's quickly define what the patterns are.
00:04:24 Simply put, React patterns are reusable solutions to common problems or challenges.
00:04:30 Think of them as some kind of ideas or solutions to most common problems.
00:04:37 There are general patterns specific to different languages or specific to different libraries or frameworks, like React patterns in this case.
00:04:46 So patterns are not necessarily tied to any programming language or technology.
00:04:51 They can be just general programming patterns or design patterns, but they can also be patterns tied to a framework or technology,
00:04:58 as you can see here.
00:05:02 For example, there is a component pattern, and it is a way to structure components to separate the UI, which is the presentational part,
00:05:13 from logic, which is the container part, or reuse behaviors with higher order components, render props, and more.
00:05:22 These are component patterns.
00:05:24 Next, we have state management patterns and their techniques for handling data in your application, like maybe lifting state up.
00:05:35 We have all done it.
00:05:37 Using the context API to avoid props drilling or creating the reusable custom hooks.
00:05:43 You might have even used these without knowing that they're necessarily a patterns that we use.
00:05:49 Then there is a rendering pattern.
00:05:53 It's a strategy for deciding what to show, such as conditional rendering, lazy loading for performance, or using keys for efficient list updates.
00:06:05 Up next, we'll explore side effect patterns for managing things like fetching data or subscriptions using use effect and cleaning up to prevent different issues.
00:06:17 These are called side effects pattern.
00:06:20 And finally, there is an advanced pattern, a sophisticated structure like a compound component for flexible APIs or portals for rendering outside the main
00:06:32 DOM tree.
00:06:33 We'll even explore those.
00:06:36 So we'll learn and implement all sorts of different strategies or patterns in each one of these pattern categories.
00:06:44 So as you might've seen, these are not necessarily single patterns, like an advanced pattern is not one pattern or side effect pattern is not one pattern.
00:06:53 These are basically categories of different patterns and we'll explore the most popular one among each one of them.
00:07:03 So tell me in the chat how many of these have you already learned about before, maybe used them in your code, or maybe you don't yet know how they look
00:07:12 like before exploring them, but they might sound familiar a bit.
00:07:16 I mean, we have all seen about state management.
00:07:18 We have all handled it.
00:07:19 We have all figured out what to render, right?
00:07:21 We have all figured out how to present some UI and separate it from logic.
00:07:26 It sounds like something we're doing every day, maybe without knowing about it.
00:07:30 Am I right guessing that or did you actually go ahead and kind of study how you would approach building those code bases?
00:07:37 Yeah, Florian says probably 90% of them, some more, some less.
00:07:41 And that's what I point your attention to is that typically while learning how to code or while reading the documentation,
00:07:50 Um, already you will have learned how to build code in the right way, but sometimes it's just good to know why you're doing it the way you're doing it.
00:07:59 So you can then maybe change it, deviate from that rule, right?
00:08:03 Because if you know what the rule is about, then you can break it because you know what it does and you know what else can you extract from it by maybe
00:08:11 changing the way that your code looks like.
00:08:13 So let's talk about higher order components.
00:08:17 You guys called it, it's first in the list.
00:08:20 It's a function that takes in a component as an argument and returns a new component with additional behavior or functionality.
00:08:30 It's used to reuse logic across multiple components without duplicating code.
00:08:38 And applications use it that require common functionality for multiple components, such as user authentication, error handling,
00:08:47 logging, or some common UI.
00:08:50 Here is a simple example.
00:08:52 Here, with authentication function, is a higher order component, typically known as HOC.
00:09:01 It takes in a component, which is a React component as an argument, and returns a new functional component, which has some conditional logic into it.
00:09:13 When I teach beginners higher-order components, it's not the React side of things that they're confused with.
00:09:20 It's actual JavaScript side of things.
00:09:23 Because let's be honest, even in plain JavaScript, vanilla JavaScript code, we don't typically see two different arrow functions one after another,
00:09:33 right?
00:09:33 So especially for beginners, this can be very confusing, but even for some people that have used JavaScript before, because it's not something that we
00:09:41 commonly see, but hey, that's why we know it's a higher order component.
00:09:47 So how does this actually works?
00:09:49 Well, first, this with authentication wrapper adds extra logic such as authentication check to the other component.
00:09:59 And then it decides whether to render the original component that has been passed as an argument or something else.
00:10:08 Let's look at it one more time.
00:10:10 In our dashboard, it's a component that says, welcome to dashboard.
00:10:15 Then we can wrap it.
00:10:18 So with authentication function acts as a wrapper to which we pass the dashboard.
00:10:22 Then the with authentication gets in that component, checks whether we authenticated.
00:10:28 If not, it redirects the login, else it displays the component.
00:10:33 This is pretty clear to all of you, right?
00:10:36 And I'm guessing even some of you might have used it before.
00:10:40 Even though I do agree sometimes when I see it, I'm like, oh, okay, so we're doing a HOC thing right here with this double arrow function return.
00:10:48 But yes, once you kind of think about it for a second, it all makes sense.
00:10:53 But now, let's actually dive into our starter repository.
00:10:57 As I said, you can or you don't need to, if you don't want to follow along.
00:11:03 It's totally your choice.
00:11:05 I would actually like it if you typed in the chat, whether you typically prefer to code along or you prefer to just watch along these workshops.
00:11:15 So just say code along or just say watch, depending on your preference, because that's going to help me a lot to prepare upcoming workshops as well.
00:11:23 Unfortunately for me, it seems to be about 50-50, but it's leaning more towards the watch side.
00:11:31 Based on that, I will kind of cater my explanations a bit so you can watch it.
00:11:35 But if you're quick enough, you should be able to code along as well.
00:11:41 Great.
00:11:41 With that in mind, let's see what we have here.
00:11:44 I will first run MPMI to install all the necessary dependencies.
00:11:51 And then I will run npm run dev to run it on localhost 5173. Once we run it right here, you should be able to see something that looks like this.
00:12:00 It's simply a list, an ordered list of different routes.
00:12:05 And when you click on each one, you'll notice that it points to that specific React page.
00:12:11 You'll also notice that there are two different versions of each one of these links.
00:12:16 There is a specific pattern we're exploring, one without the pattern and then one with the pattern.
00:12:23 So, let's see how this HOC works without a pattern.
00:12:27 We simply have a profile and a dashboard, and both of them are trying to load some data.
00:12:34 Very straightforward example that most of us have likely encountered or worked at on some point.
00:12:41 We have two distinct components on a single page simulating a dummy fetch scenario to display a loading indicator followed by results after a short delay.
00:12:52 Let's also see how this looks like in code.
00:12:54 I can head over to routes, HOC, and then I'll head over into the without.jsx.
00:13:03 Is the code large enough?
00:13:04 Do you want me to maybe make it a bit smaller so we can see more stuff on the screen?
00:13:08 So as you can see here, we have a functional component called profile, and we also have a functional component called dashboard.
00:13:16 And then we have one component that renders both of them.
00:13:19 Pretty straightforward, right?
00:13:21 Now, what we can notice is that the function profile actually has a lot of logic.
00:13:28 And I'm really talking a lot.
00:13:30 That is doing the loading right here.
00:13:34 We're setting the loading, we're setting the use effect, we're fetching some data or at least simulating the fetch of the data.
00:13:40 And then if it's loading, we return the spinner.
00:13:44 Else we load the data and then show the profile.
00:13:47 Now what happens here is we have a lot of this code only to handle loading.
00:13:52 And then check out the dashboard.
00:13:54 Same thing happens right here as well.
00:13:58 it's absolutely the same code.
00:14:00 And this is code duplication, which we never want to have.
00:14:03 And this is the perfect use case for when you might want to implement a higher order component.
00:14:10 If you have multiple components fetching different data across a page, this repetition of loading logic can quickly become excessive,
00:14:18 especially on larger applications.
00:14:20 So first, recognizing what can be reused is the first step toward making it reusable.
00:14:29 Okay, perfect.
00:14:30 So now let's actually, you know what, let's pull this width on the side right here, if it's not too crowded.
00:14:39 And I'll teach you how we can implement a higher order component.
00:14:45 So first things first, we'll create a new higher order component called width loading.
00:14:50 Okay.
00:14:51 That's going to look something like this.
00:14:53 Function.
00:14:55 Width loading, which is going to take in a component as well as maybe some kind of a delay, which we can default to 2000. And I am noticing that it's getting
00:15:06 a bit crowded.
00:15:07 So I'll actually pull just the width right here.
00:15:09 And then later on we can compare the differences.
00:15:12 Perfect.
00:15:12 So this is just a regular JavaScript function, for now at least.
00:15:16 But when it becomes a higher order component in React is when we return a new thing right within it by saying return function with loading,
00:15:28 which can take some props.
00:15:30 And then here we can define that loading logic.
00:15:34 By the way, you can see that copilot is automatically suggesting it for me.
00:15:38 Um, but in this case, I can maybe just grab it from here because we already know that it's going to be more or less the same for all of these.
00:15:46 So I will simply copy this entire if the use effect and the use state and paste it right here.
00:15:53 So we can handle the logic within this inner part of the higher order component.
00:15:58 That's going to look something like this.
00:16:00 So to make things clear and explain it in different ways, basically what we're doing here is we're using functional component definition.
00:16:08 function with loading, and before we used an arrow function syntax, right?
00:16:15 So with loading is the same as const with loading is equal to a function that looks like this, and then a new one that takes in the component and then
00:16:27 basically returns some additional code.
00:16:30 Either way is fine, but I think this just makes a bit more sense when you see it visually.
00:16:35 Now tell me, in your React or Next.js applications, what do you prefer?
00:16:40 Do you prefer declaring your functions like this, or maybe using const func is equal like this?
00:16:47 So function keyword or arrow function.
00:16:49 Once again, to my luck, it seems to be split evenly 50-50.
00:16:56 Although now starting to lean more towards the arrow functions.
00:16:59 Either way is totally fine.
00:17:01 You just have to understand that they're both the same thing.
00:17:03 So with that in mind, We are now handling the logic, but we'll have to make it a bit maybe abstract or maybe agnostic.
00:17:13 So it works with any kind of function we pass into it.
00:17:17 So I'll simply pass delay right here of 2000, clear the timeout.
00:17:21 And if loading, I will take in the props and instead of rendering just profile right here, I will render props.title because we can pass the title of that
00:17:31 component right there and then render the spinner.
00:17:34 Finally, the question is, how can we render this component?
00:17:38 Well, it's going to look something like this.
00:17:40 Below the loading, I'll say return component to which I'll spread all the props that we pass into the first HOC.
00:17:49 And that's it.
00:17:50 Now, what we can simply do is go a bit below.
00:17:55 where we have a function dashboard and a function profile.
00:17:59 And we can simply wrap both of these with the higher order component.
00:18:06 That's going to look something like this.
00:18:08 Const profile with loading.
00:18:10 You call the higher order component with loading, you pass in the component and you pass a delay like 1000 or 200 or 2000 milliseconds.
00:18:19 And then we can do the second one, dashboard with loading.
00:18:22 And you can even define some special delay if you want to, or you can change some things is what I'm trying to say.
00:18:29 Whatever props you pass into this one will get passed right here when you're calling that component.
00:18:35 Finally, instead of calling them profile and dashboard, you can simply call profile with loading, pass the title of profile,
00:18:43 and dashboard with loading, and pass the title of dashboard.
00:18:47 And that's going to allow you to end up with a function that does only one thing.
00:18:52 So we are also using another pattern right here, which makes sure that a single component does only one thing.
00:18:59 Function profile is rendering the user data and function dashboard is rendering the data for the dashboard.
00:19:06 Where we have this new with loading that then applies the loading to both of these components.
00:19:12 This ensures cleaner, more modular code and avoids repeating the same loading logic across different components.
00:19:19 What you could do now is maybe extract this into some kind of a utils file or folder and then use it across your entire code base.
00:19:28 Okay.
00:19:30 Perfect.
00:19:31 So let's go back to the website and let's see whether we have properly implemented it.
00:19:36 You can see this one loads first, this one loads second after three seconds.
00:19:41 And that's it.
00:19:42 The functionality is the same, but now you understand a bit more about how we're using those higher order components.
00:19:50 Again, just a simple example, but I think you can get the idea.
00:19:56 It doesn't have to be used just for loadings.
00:19:58 It can also be used for error handling.
00:20:01 It can be used with testing.
00:20:03 It can be used with toast.
00:20:06 Florian is just literally feeding different examples to me right now.
00:20:10 I was just about to start listing examples and he said, you know, with theme, with toastify, with router, you can just provide so many things to higher
00:20:20 order components to feed the inner components within them.
00:20:24 And also somebody says testing 99% of use.
00:20:27 Yes, you can also use them for testing.
00:20:30 Perfect.
00:20:31 So many examples, super useful.
00:20:34 If I dare to say maybe the most useful React pattern, this workshop is done.
00:20:38 You've learned a lot.
00:20:40 We can end it here.
00:20:41 Of course, I'm just kidding.
00:20:43 Let's dive into the second pattern of the day, which is the composition pattern.
00:20:50 The composition pattern allows components to be composed together to build more complex UIs by combining smaller, more reusable pieces.
00:21:02 It provides greater flexibility by allowing components to be combined in different ways, enhancing both the reusability and scalability.
00:21:12 And it's often used in very complex UIs where components need to be customizable and composed in different ways, such as layout systems,
00:21:22 forms, or configurable widgets, even dashboards.
00:21:26 So here, I prepared a very simple example.
00:21:30 A button.
00:21:31 Believe it or not, yep, button can be a composable component or a composition component in this case.
00:21:38 This button is an example of the composition pattern.
00:21:42 Very small demo, we'll see more of it later.
00:21:45 But this pattern allows you to create smaller reusable pieces of code that can be modified and used anywhere in your application instead of starting from
00:21:55 scratch every time.
00:21:57 With the composition pattern, you can use the button component in different contexts with various styles and children without modifying the main button code,
00:22:06 which makes the component reusable and decouples it from specific use cases, promoting its flexibility and maintainability.
00:22:14 Let's now go back to our starter to explore it on a more complex example.
00:22:19 I'll head over to the composition part and head to the without part.
00:22:24 First, might be better to just show you what this composition example actually is.
00:22:32 So let's go back to the browser and head over to composition without pattern.
00:22:36 This is a standard form setup, something most of us would naturally do.
00:22:41 Even in some of my workshops or tutorials, I'd go with this familiar and straightforward approach.
00:22:47 Again, just a bit of comfort when it comes to very easily setting up all of these inputs right here.
00:22:52 You have a div with a label and then an input.
00:22:56 And then you have another div with another label and another input.
00:23:00 I mean, jokes aside, while this approach works, it's not sustainable in the long run.
00:23:07 Especially when dealing with large forms and multiple forms that share common UI elements or styles.
00:23:13 And you might think, hey, Adrian, I'll just create some Tailwind CSS styles or utilities and keep it as is.
00:23:20 Fair enough, but that's not the most effective solution.
00:23:24 Forms often involve more than just tiles.
00:23:27 They require handling validations, errors, and other functionality.
00:23:32 And that's why we can head over to composition with And I'll teach you how to implement the composition pattern.
00:23:40 So right here, we have almost the same exact thing as without, but I just haven't used those actual functions that handle the change of the inputs or handle
00:23:50 form submission.
00:23:51 So what we can do is declare a new composable or wrapper component that handles the structure or submission of the form,
00:24:00 making it reusable for any kind of form.
00:24:02 I'll call it function form that'll accept children as well as the onSubmit functionality.
00:24:09 Because let's be honest, every function or every form needs to have an onSubmit function.
00:24:14 There we go.
00:24:16 After that, we can make a return.
00:24:18 And the only thing that this form will do is just return a form that'll have an onSubmit equal to onSubmit.
00:24:31 as well as a class name equal to form.
00:24:35 Okay, just to provide some styling, right?
00:24:38 And then we can render the children right within it.
00:24:42 Very simple form component.
00:24:45 Now we can create another component that acts as another wrapper.
00:24:49 I'll call it function form field, which is gonna be equal to, or just regular function like this.
00:24:58 Either I'm having some kind of a stroke or my keyboard is stopping to work because I'm missing every second character.
00:25:05 But yeah, we can have a name right here, and then we can have a render form.
00:25:10 So we can render different fields of different kinds of names.
00:25:15 And that's going to look like this, return a div where we can render, and then a field of that specific name.
00:25:25 What we can also do is maybe create some kind of a simpler wrapper called function, form, item, and this one will accept children.
00:25:38 And specifically this one will be structured for each individual form element inside of a div with consistent styling and layout across all form items.
00:25:49 So we can say return div with a class name equal to form item.
00:25:59 And it'll simply render the children right here.
00:26:03 So it's going to look something like this.
00:26:04 I think it's small enough.
00:26:05 We can even put it in one line right here.
00:26:09 Okay, so we have created three different composable, very simple wrapper components.
00:26:15 And let's just do one more to really nail it.
00:26:19 We can have a function called form label, and this one will accept an HTML4 property, as well as children.
00:26:34 And once again, you can guess it.
00:26:36 The only thing it'll do is it'll return a label with an HTML4 equal to HTML4.
00:26:47 That's going to be four, not form, as well as we can pass something within it.
00:26:52 And that's going to be a class name equal to form dash label.
00:26:57 And then we can pass the children right within it.
00:27:01 Of course, what you could have done is also just used arrow functions for all of these with immediate returns.
00:27:06 Let me actually see if Copilot will listen to me right now and turn these functions or function declarations into immediate return arrow functions.
00:27:22 might be a bit cleaner to read.
00:27:24 Let's see if it listens to me.
00:27:26 Sometimes it does, sometimes it doesn't, you know how it is with AI chatbots.
00:27:32 But yeah, in this case, I actually would prefer to use just a regular arrow function.
00:27:37 There we go.
00:27:38 I think it did it.
00:27:39 And I think it did it correctly.
00:27:41 Yeah.
00:27:41 So you can have an instant return right here, here, here, and here.
00:27:45 And you can think of these as wrapper or some kind of a composable components.
00:27:50 You could go even further.
00:27:52 You can have a composable component even for a form message.
00:27:55 So const for form message, which takes in a message and then also returns.
00:28:05 something like a p tag with a class name or form message.
00:28:11 And then within it, you can return a message.
00:28:14 I think you're starting to get the gist of it, or maybe you have gotten it after I have created our first or second part or second composable component.
00:28:23 But this is the idea.
00:28:27 Now we can use all these separate components and which do their own specific things and do not depend on each other and create a new form that ties everything
00:28:38 together like Lego blocks.
00:28:41 So that's going to look something like this.
00:28:44 We can head down to the rendering part.
00:28:46 Everything else remains the same and we can create a new form.
00:28:51 So let's say form, which will take in an on submit equal to handle submit as forms usually do.
00:29:00 And we don't have to pass a class name to it because it already knows how it should look like.
00:29:06 Next, we can create a form field.
00:29:09 So individual fields with custom rendering logic by saying form field.
00:29:15 And this will be a self-closing component, which takes in a name equal to name.
00:29:22 And it can also take a render field where it will render a name.
00:29:26 And then within it, we can render a form item composable component, which is another component we have created within which we can have a form label.
00:29:37 That will have an HTML four equal to name and within it we can render name as well.
00:29:45 Finally, we can have a form control, which can wrap an input.
00:29:50 Let's see.
00:29:51 Why is it not finding it right here?
00:29:54 Did I create a form control or did AI eat it?
00:29:57 It's possible that it got lost somewhere.
00:30:01 Or maybe I just skipped it over.
00:30:02 But anyway, form control should be a very simple component, which takes in the children and then returns a div with those children.
00:30:15 And think in this case, we don't even have to have a class name.
00:30:18 This should be enough.
00:30:20 And now we can head down.
00:30:22 We have a form control.
00:30:24 And then within the form control, we can render an actual HTML input.
00:30:30 Could have you made this a composable component?
00:30:33 Sure, you could have.
00:30:35 And we can also provide a type of text, maybe like a name equal to name, maybe an ID equal to name as well, a value equal to form data dot name.
00:30:47 You know, all the usual things that all the inputs have, maybe a handle change.
00:30:53 and even a class name to which we can now provide a CLSX.
00:30:59 Always it can have a form input class.
00:31:02 And then only sometimes when there are errors here, then we can render a border red of 500. Else it'd have a border gray of 600. Something like this.
00:31:17 Finally, right below the form control, we can also render a form message to which we can pass the message equal to errors.name.
00:31:28 And what we have done here is we have basically used different individual composable or wrapper components and put them together in like Lego building blocks,
00:31:38 right?
00:31:40 What you can do now very easily is maybe copy this entire form field and then duplicate it somewhere below.
00:31:46 So I'll head right here below and duplicate it.
00:31:49 And now you can maybe change this one to be, let's say, email.
00:31:54 Also change, well, check this out.
00:31:58 Nothing else has to change.
00:31:59 As soon as you change the name to email, render will automatically take that name and then render it across different places.
00:32:06 Where we do have to change it is here, formdata.email as well.
00:32:13 And I think that's more or less it, just the errors.email right here and the errors.email right here as well.
00:32:21 And then we can render a button.
00:32:25 That'll be of a type submit.
00:32:27 I'm sure that this is something that all of you are used to, especially when it comes to writing your rendering code like this,
00:32:35 when rendering different form items, right?
00:32:37 We're used to this part, even though we're not necessarily used to this part right here, right?
00:32:44 This one.
00:32:46 I'm going to be honest, feels a bit wrong.
00:32:49 It feels like we're breaking things down too much.
00:32:52 It just feels like we're over-engineering, over-complicating stuff.
00:32:57 But not really, right?
00:32:59 Because in our day-to-day, we actually write code that looks like this, which is derived from this.
00:33:09 So let me just head over to the demo and first remember that this is just a simple demo.
00:33:14 You can always take it further by creating more composable components like inputs or buttons.
00:33:22 So let's head over into Composition Wood Pattern.
00:33:28 You can see that it works and behaves in the same way.
00:33:30 It has two different fields, name and email.
00:33:35 And you might still wonder, Adrian, this looks good, but are we really going to break the code so much?
00:33:42 It feels like we're going to such minute granular levels.
00:33:48 Well, I'm going to be honest, it depends on your application and its needs.
00:33:52 For larger applications or cases where forms and buttons need to be reused extensively, I would highly recommend this approach.
00:34:01 And again, it's not just my personal opinion.
00:34:04 It's a widely adopted practice in the industry.
00:34:08 Many seasoned developers follow this pattern.
00:34:10 And in fact, if you ever explored Shazien's form management, you'll notice that the composition pattern that they use is strikingly similar to the one
00:34:20 that I have just explained to you.
00:34:22 It is basically the same.
00:34:24 So, this pattern isn't just for forms.
00:34:27 Chatciennes and others use it across various components.
00:34:33 So, give it a try soon, even though it might feel like we're over-complicating and just over-breaking things down.
00:34:41 Actually, the code that you end up having within your components by using those composable components is so much cleaner and so much more reusable.
00:34:51 Sometimes you might not even need to do it because you will already be using a library like ChatCN or something else that does that for you.
00:35:00 But it's good to know that that creator of that library actually uses the approach and the pattern we just discovered.
00:35:08 If so, we are ready to move on to the next pattern.
00:35:12 The Provider Pattern.
00:35:15 The Provider Pattern centralizes the shared logic or sorry, it centralizes shared logic or state into a higher level component called the Provider that
00:35:28 makes it available to its children via context.
00:35:32 So, simply put, it enables sharing state or logic across deeply nested components without props drilling, making it more efficient and organized.
00:35:45 It's used when multiple components, often in deeply nested trees, need access to the same state or functionality, such as authentication,
00:35:55 state, or a theme.
00:35:57 Over here, we have such one example, where we create a context object that holds the theme state and the function to update it,
00:36:09 theme context, and theme provider.
00:36:12 This provider manages the theme state and provides it to the rest of the application via context.
00:36:20 It does so by wrapping its children components into theme context dot provider.
00:36:28 After defining the provider right here in the theme component, we create a component that consumes the theme context.
00:36:35 You can see that right here.
00:36:38 And finally, we wrap all components in the theme provider like so.
00:36:43 Basically, this is a provider pattern using React's context API.
00:36:48 And you can create different patterns by manually passing down the shared state through props or other way around.
00:36:55 Alongside this pattern, there's another highly used pattern called the compound pattern.
00:37:01 And they go both hand in hand.
00:37:04 You can think of the compound pattern as the combination of composition plus provider pattern, if that helps.
00:37:11 But it's not necessary to always use the provider pattern with the compound pattern or vice versa.
00:37:19 So before we dive into the examples, let's check what a compound pattern is.
00:37:25 It is a way for components to work together as a group while keeping their logic and state shared among them, typically using context.
00:37:36 It allows for building components that are closely tied together, but still flexible, reducing the complexity of prop passing.
00:37:45 And it's used in UIs with related components that need to share state or functionality, such as tabs, accordions, or form field groups.
00:37:57 Let's see it in a code example.
00:38:00 Here, we have the accordion provider.
00:38:04 So this accordion component acts as the provider for the shared state, showing use case of provider pattern.
00:38:12 And on the same node, it also defines the layout for any kind of accordion, like a composable component.
00:38:19 We can then consume this accordion context right here within accordion item, which is another self-composed component managing some logic as well as UI.
00:38:31 And then together, we can use these components as the accordion holds both of them together and the shared state as well as the UI.
00:38:42 That's going to look something like this.
00:38:45 So it's basically a combination of both the two things that we covered so far, but let's go back to the code base to see exactly how that works on a bit
00:38:55 of a bigger example.
00:38:56 So let's close this file and head over to compound index.jsx.
00:39:05 And let's also explore it in the browser.
00:39:08 So if I go here, localhost 5173, we can check out the compound components pattern.
00:39:17 It's a simple tab feature that allows you to switch between different tabs, typically by using states to determine which tab is active.
00:39:28 Super simple.
00:39:28 We have all done it.
00:39:30 Sure, you could keep everything in one file and manage the state directly without using the provider pattern with the context API.
00:39:38 But that works for simple applications.
00:39:40 And as your application grows with more tabs or content, writing thousands of lines of duplicated code isn't practical.
00:39:48 And this is where the compound pattern comes in handy.
00:39:54 It'll help you keep your UI reusable while the provider pattern helps you share state logic across different components.
00:40:03 This way, you avoid prop drilling and don't end up in a messy state.
00:40:07 The context is only for those elements and is limited to the logic, so it won't be shared or used anywhere else.
00:40:16 So you can see that code right here.
00:40:19 Let's explore it together.
00:40:21 In this case, I decided to immediately provide a final solution so you can see exactly how it behaves because this is a combination of two different patterns.
00:40:30 Cool.
00:40:31 So let's check it out.
00:40:32 First, we create a context.
00:40:35 Then we define tabs, which holds the state and passes that state over to the tabs contact that provider.
00:40:42 And then children will have access both to the active tab and set active tab.
00:40:48 We have another tabs list, which holds just the list of the tabs.
00:40:52 And then we have yet another one, which is just a single tab, which then uses that context.
00:40:57 Finally, when we put it all together, we have the tab panels, which uses the context.
00:41:03 And then it also gets into children and can switch the active tab based on the context data.
00:41:10 At the end, it's going to end up looking something like this.
00:41:14 Again, I didn't write the code because the logic is very similar to what we did earlier with composition.
00:41:21 But the only big difference being now is that we're sharing state logic using the provider pattern.
00:41:28 I hope that makes sense.
00:41:31 Again, you might need to revisit this example a bit and try to re-approach both of these previous patterns on their own and then hook them together and
00:41:41 it'll all start making sense.
00:41:43 I do agree that it is a bit of an overkill for simple tabs, but on larger applications where there's a lot of tabs, or just as a small demo to show you
00:41:53 how you can use this concept on larger applications and larger examples and larger pieces of code, I think it makes sense.
00:42:01 And I'm glad to hear that.
00:42:04 And I'm glad to hear that you guys like it and it makes sense.
00:42:08 Perfect.
00:42:10 So with that in mind, I want to go to yet another pattern, and it's called a portal pattern.
00:42:19 It enables rendering of a component outside of a parent component DOM hierarchy, typically used for models, tooltips, or pop-ups.
00:42:32 Okay.
00:42:32 So when is this actually used, the portal pattern?
00:42:36 It's used when you want to allow elements to visually appear outside of the normal flow of the DOM, like on top of other elements,
00:42:46 improving accessibility and UI control.
00:42:50 It's used in scenarios like models, tooltips, or any other component that requires rendering outside of the normal DOM flow,
00:42:59 such as model dialog box that overlays on top of other content.
00:43:05 And, of course, I have an example.
00:43:08 Here, we create portals using React DOM that allows rendering of components outside of the normal DOM hierarchy.
00:43:16 Then, we have a modal component that uses React Portal to render the modal outside the parent component.
00:43:24 You can see that here.
00:43:25 Return ReactDOM.CreatePortal where we have a div with a class name of modal, and then we pass the children right within it.
00:43:34 To it, you also have to pass the document.body, which is a DOM node to render to.
00:43:40 Basically the location in the DOM where this JSX needs to be rendered or inserted within.
00:43:47 And finally, we can show a model at a different place, regardless of the rest of the DOM tree.
00:43:54 Perfect.
00:43:55 So let's head back to the code and let's head over to the portal without .jsx.
00:44:05 First, I want to actually open that up within localhost 5173 and head over to portal.
00:44:12 Let's go without pattern first.
00:44:17 Here we have a regular page where you can open up a model that appears on top of the rest of the content and then you can close it.
00:44:25 Works seamlessly.
00:44:27 Basic model, you can open it by visiting the portal without the route, something that we commonly do.
00:44:33 And while this works just fine, there are issues like potential z-index conflicts, overflow problems, and event handling issues as the model is confined
00:44:45 to the parent component layout.
00:44:48 So now, let's head back over to the code and let's address this using the portal pattern, which moves the model or any other element outside its parent
00:45:01 and places it where we specify by passing a second argument.
00:45:05 Essentially, it portals the element from its default position in the HTML to a desired specified location.
00:45:15 So now we can head over to portal with JSX and I'll teach you how to implement it.
00:45:24 First things first, we need to import React DOM from React DOM.
00:45:29 And then we can head over right here where we can implement the portal pattern.
00:45:35 First things first is check whether isOpen is true.
00:45:40 If it is, only then do we want to show this model.
00:45:44 What we can do here is say React DOM.
00:45:48 dot create portal, and then we can pass whatever JSX we want to show.
00:45:55 The first argument for any kind of portal is JSX.
00:45:58 In this case, it'll be the model code we want to display.
00:46:02 So I think we can even pull it from portal without.
00:46:07 Yep.
00:46:08 It's going to be this same exact model, which I'll pass as the first parameter right here.
00:46:14 And then as the second argument to this function, right after the JSX, we can pass the container, define the location to which this JSX has to be rendered.
00:46:24 It can be anywhere in the DOM.
00:46:26 Over here, we're specifying to render DOM model content directly inside the body tag.
00:46:32 So that's going to be document.body, like this.
00:46:36 and it'll be treated as main children of the body element or the tag.
00:46:41 But as I said, this can be any other DOM selector.
00:46:45 Now, let's do a comparison.
00:46:48 I'll head back over here, without the portal, I will open up the model, and then let's observe where the element is located within its hierarchy.
00:47:00 If I go to Inspect, make this a bit smaller so we can see it, Go to elements and collapse this down just a bit.
00:47:10 Check this out.
00:47:13 It makes sense where it is, right?
00:47:15 Right here within the actual div, within the main, within the specific page.
00:47:21 But now if we head over right here to portal with pattern, open it up and try to inspect it.
00:47:32 You can see that it is right here.
00:47:35 I think it is next to the root.
00:47:37 Yep.
00:47:37 You can see div ID root within the body.
00:47:40 And then we have another div ID portal and we immediately within it, there is the div containing that portal.
00:47:48 So you can basically decide wherever you want to put it to and it'll portal right there.
00:47:57 Basically, the point of the story is that it is no longer within the parent component, which keeps things clean.
00:48:05 We simply put it in the document body.
00:48:10 Perfect.
00:48:10 If I head back over to the code.
00:48:13 Hopefully this makes sense.
00:48:15 Let's just see.
00:48:17 Yep, this is perfect.
00:48:19 Maybe it's not structured well.
00:48:21 I could have indent it more properly, or maybe what would make a bit more sense visually is to define this as another piece of JSX right here,
00:48:30 like modal.
00:48:32 is equal to this JSX code.
00:48:35 Or you know what, I think I just copied it and we in this case didn't even need the class name of portal.
00:48:40 It could have just immediately been there, which is why it might have been a bit misleading because in both cases we had portal.
00:48:48 But in this case, you could have just rendered this inner div and it would still work properly.
00:48:54 Anyway, the create portal works in a way that you provide the JSX as the first parameter right here, and then you provide where you want to teleport or
00:49:03 portal that part of JSX to.
00:49:06 Perfect.
00:49:06 Hopefully this makes sense.
00:49:08 You can use the portal pattern for models, tooltips, or even drag and drop overlays.
00:49:14 This brings us to the last portal or not portal, but rather pattern within our application.
00:49:22 And that is renderPropsPattern, which is a technique in which a component receives a function as a prop and calls it to dynamically determine what to render.
00:49:36 This is also known as functionAsChild pattern.
00:49:40 Typically, it shares functionality while allowing flexibility in how components are rendered.
00:49:46 Similar functionality, but flexibility in how components are rendered.
00:49:51 It's used for managing hover states, animations, or data fetching.
00:49:57 And of course, here's an example.
00:50:00 Here, you can see the render props pattern where it receives a function, render, as a prop from the parent.
00:50:08 hoverable, hovered set hovered, but rendered right here is taken as a prop.
00:50:13 And then in the app, we can decide what that render function will do by passing a callback function.
00:50:22 The benefits of this pattern of passing functions as props to other components is that it decouples the logic of state management from rendering logic,
00:50:32 meaning the parent, in this case hoverable, provides the behavior, like hover tracking, but the child component, in this case the app,
00:50:42 controls how to display that behavior.
00:50:46 It allows parent components to expose data or functionality to its children without deciding how the children will display or use that data.
00:50:57 This pattern is used to avoid tight decoupling between components or renders.
00:51:04 A tightly coupled means that components, modules, or pieces of code are highly dependent on each other.
00:51:12 And while it not may be immediately obvious or visually impactful in some cases or applications, loose coupling is a crucial concept in programming because
00:51:23 a writing code that is loosely coupled promotes flexibility, simplifies maintenance, or testing, and it enhances reusability because components can be
00:51:36 modified or replaced without affecting others, making the code more adaptable and easier to manage.
00:51:44 In this case, what I'm explaining is basically a programming design pattern called loose coupling.
00:51:53 As you can see, the patterns don't necessarily have to be connected to a specific technology, framework or library.
00:52:02 but they can also be general programming patterns.
00:52:05 But then it's pretty cool to see when you have a general programming pattern and then when it gets transferred over to some language or framework specific pattern,
00:52:14 like it does in this case.
00:52:16 And now I have prepared a demo for this.
00:52:18 Okay.
00:52:19 So let's head over to render props, index.jsx.
00:52:24 And let me explain what's happening here.
00:52:27 As you can see, once again, there is no before and after.
00:52:29 We only have a simple single piece of code and I'll try to explain it.
00:52:35 And I think it'll immediately click how and why this is working as it is.
00:52:41 So first of all, we have.
00:52:45 functions or components called USD as well as euros.
00:52:51 This function displays the amount in USD, American dollars, and this one displays it in euros.
00:52:58 Next, we have a function called currency converter.
00:53:04 This component handles the core logic of currency conversion.
00:53:10 It manages the amount entered in US dollars and fetches the exchange rates.
00:53:17 And then it calculates the converted values for USD and Euros based on the entered amount and the exchange rates.
00:53:26 Pretty simple.
00:53:26 I think currency converter is one of those programming examples that most of you have already seen.
00:53:34 It's a perfect example where a function can take input, do some processing, and then render an output.
00:53:41 And finally, we have a function called renderPropsPattern.
00:53:47 What happens here is that the currency converter component accepts two props, renderUSD and renderEuros, which are functions or components that define
00:54:00 how the converted euros and dollars will be displayed.
00:54:05 Instead of hard-coding the display logic, the component allows you to pass in custom rendering functions or components for both euros and dollars.
00:54:14 I think that's because we have different fixed amounts.
00:54:18 In this case, it's very similar, but I think you can imagine in how many places this could be used.
00:54:25 Currencies are a great example because sometimes you might want to put a dollar sign upfront, like this, and sometimes you might want to just say euros
00:54:35 or you might want to put it at the end.
00:54:37 So whenever you want to decide how you want to render different things, and you want to have the flexibility to be able to pass that,
00:54:45 you can pass it as a prop.
00:54:49 And again, this connects to many different patterns that we have explored before.
00:54:53 One is passing props.
00:54:55 One is again, doing different parts of the logic in different pieces.
00:55:00 Like this ensures that you have the rendering logic right here in components.
00:55:05 And then the currency converter actually deals with fetching the data, fetching the exchange rate.
00:55:11 And then you can use this function right here to render it properly.
00:55:17 Makes sense?
00:55:18 Let me just explain how it works one more time.
00:55:21 So when a user enters the amount into the input field, the component will update the amount state.
00:55:29 That is this state right here, based on this input.
00:55:34 Once the exchange rates are fetched, and they're fetched right here, Maybe we should update this to run whenever we change the amount.
00:55:43 That's also something we can do.
00:55:45 But for now, I'll leave it as it is.
00:55:47 Then the calculated amounts are converted for both USD and Euros.
00:55:52 And then we use the props, renderUSD and renderEuros, depending on which one we have, to basically show them both here.
00:56:02 And think in this case, we're showing both.
00:56:05 Perfect.
00:56:06 So you can choose any kind of way in which you want to render things.
00:56:10 This can be useful for, as I said, currencies.
00:56:12 Another example, I used to work in a startup where we were working on a singular payment processing form that combined many different payment methods.
00:56:23 And that is just a mess because you have single logic, which is for entering, accepting the data, to be able to process those payments.
00:56:32 But then you have payment processors like Stripe.
00:56:35 You have card payments.
00:56:36 You have many different options like PayPal.
00:56:41 And then for different countries, there's also different payment providers.
00:56:44 It would be super useful to have one function that says render payment methods, and then depending on different criteria,
00:56:53 you can pass how you want to render each one of these payment methods.
00:56:58 It can be based on different criteria, like maybe the countries where people are from.
00:57:04 Okay, I'm over explaining here, but this pattern makes the currency converter component flexible and reusable.
00:57:11 You can pass different rendering logic like USD, Euros, without changing the core logic of conversion, making it adaptable to different display needs or
00:57:22 other components.
00:57:23 This is basically a loosely coupled component, as we discussed.
00:57:28 And finally, let's head back and check how it looks like in the demo.
00:57:33 Render props pattern.
00:57:35 We can render it right here.
00:57:37 I'm going to enter the amount.
00:57:39 We should have defaulted this to zero.
00:57:41 We can do something like 250 and we can get the immediate exchange rate in both of these components.
00:57:47 And this rendering factor is coming from completely separated components, which we pass into the other function to decide how they're going to be rendered.
00:58:00 Perfect.
00:58:02 Make sense?
00:58:04 I think I over-explained myself a bit in this one, but I hope it's understandable.
00:58:08 You get the full flexibility of how you want to render things while still retaining the possibility to keep the core logic intact.
00:58:19 Perfect.
00:58:20 Glad it makes sense.
00:58:21 That's it for this workshop.
00:58:23 Like we explored many different important programming concepts and just some general things as well.
00:58:30 We explored some very powerful React patterns like higher order components, provider pattern, function as children, portals as well.
00:58:40 And I didn't want to keep it too long and too overwhelming because we already covered like five or six different ones.
00:58:48 And you'll also have access to this entire code.
00:58:51 So you can check them if you want to revisit it, both the starter as well as the final code.
00:58:57 So as I said, you have both the starter as well as the final to be able to check how all of this works.
00:59:03 You can also find it in the chat.
00:59:05 I just dropped it in there.
00:59:06 It's full of real world examples that will help you see those patterns in action.
00:59:12 So play with them and before you know it, they'll feel like second nature.
00:59:17 And you'll even start noticing smart things that creators of different frameworks or libraries, like maybe Evan for Vue or maybe different people for React
00:59:29 and even Angular, you'll notice, hey, he actually did this.
00:59:34 and by using a pattern and now we're writing code like this every single day because they made a conscious decision to use this pattern while creating
00:59:43 this framework or technology.
00:59:45 It'll all click and it'll just make you a better developer overall.
00:59:53 So if you have any questions or need any help, please do reach out.
01:00:01 Be that right now, right here, or reach out wherever I am on socials.
01:00:05 You can do that on LinkedIn, on YouTube, Twitter as well.
01:00:09 And just thank you so much for joining today and for sticking till the end of this workshop.
01:00:14 I'm noticing that many of you guys are still here and that's a great sign.
01:00:19 I hope you found some value in this and I'm just hoping that you're feeling inspired to take your React skills to the next level.
01:00:27 So thank you and I'll see you online.
01:00:30 You can just reach out on LinkedIn or Twitter or YouTube.
01:00:35 I'll also see you on jsmastery.pro.
01:00:38 We're working on this new platform right now where we're really thinking of a new way to help people approach learning web development through examples
01:00:49 directly within MDX files within the browser that they're learning.
01:00:53 So for example, if we turn this workshop on there, we'll be able to dive into learning how each one of these patterns works very similarly to what we have
01:01:02 had here, like different lessons where we show different examples alongside the code examples, but also the representation of that code.
01:01:12 So if that's something you're interested in learning or just staying in touch and seeing how that progresses, I'll keep you updated on that in maybe in
01:01:20 a talk on next year's Git Nation workshop or conference.
01:01:26 Once again, thank you so much for being here, sticking until the end, and I'll see you in the next one.
01:01:32 Have a great day.