In this workshop, we’ll look at some of the approaches and techniques that can be applied when making refactors or adding new features to a legacy React codebase to bring it inline with the latest approaches. We’ll cover topics such as how to use React Hooks to share component logic in a way that will allow reuse in class components; how to incrementally introduce other patterns to a React Redux app; and how to build in flexible UI components via abstractions where we are tied to some global CSS or a component library. Along the way, we’ll touch on many React patterns and state management approaches with the ultimate aim of being able to evaluate these options and let our requirements drive the architecture in moving towards a more robust and maintainable codebase.
Incrementally Adopt Modern React Patterns in a Legacy Codebase
AI Generated Video Summary
This workshop focuses on incrementally adopting modern React patterns in a legacy codebase. It covers topics such as building reusable component logic hooks, refactoring legacy code to use hooks, and using context with hooks. The importance of refactoring class components to functional components and using hooks whenever possible is emphasized. The workshop also explores the use of Redux for centralized state management and the use of context for global state. Troubleshooting and error handling are discussed, and the workshop provides exercises for hands-on practice.
1. Introduction to the Workshop
Welcome everyone to this workshop about incrementally adopting modern React patterns in a legacy codebase. I'm a software engineering coach and currently a principal engineer at Sainsburys. I've worked on various projects and have experience in training developers. Let's get started.
I guess I was just gonna ask quickly. I guess everyone's in the Discord channel. You can probably see my screen now, hopefully. That's where I'm gonna sort of post all the stuff. If you want to, yeah, feel free to clone and run the installs on the repo now, just save time later. I mean, there will be time, but, you know, it always takes a couple of minutes. But, yeah, I guess we can just start, actually, because it's 5 past, I think. Hopefully more or less everyone's joined. But, yeah, well, let me just present this. And, yeah, if you can't see what I'm presenting or talking about, feel free to just shout out. Like, if you can't see on my screen, or the code or any of those things, just let me know, I'm going to present it in full screen. I don't have two monitors now, I can't tell exactly. But, anyway, welcome everyone to this workshop about incrementally adopting modern React patterns in a legacy codebase. Yeah, you might be wondering who am I quickly, thanks for everyone's introducing themselves as well, that's really nice. Who am I? Software engineering coach, currently principal engineer at Sainsburys. For those of you that have visited the UK, you probably know Sainsbury's, big supermarket. Yeah, I've worked on lots of different things, I've been lead developer on several projects, at leen.js, my previous place where I was a partner. I've done plenty of training as well. I work with React, Kurl Academy, I was the organiser of the boot camps we were running in Portugal and London a couple of years ago. And we did sort of like trainings for developers from all sorts of places. Cool. Let me see if I can go to the next slide. Okay. Cool.
2. Introduction to React Patterns and Hooks
Welcome to the workshop on incrementally adopting modern React patterns in a legacy codebase. We will cover building reusable component logic hooks, refactoring and simplifying a legacy React Redux app, and using context with React hooks. We will also discuss the evolution of React patterns, from functional stateless components to the need for class components and the introduction of hooks. Let's explore the circumstances where class components or hooks are needed. Managing state and lifecycle methods were the primary reasons for using class components in the past, but now we have Hooks alternatives for most cases. It's important to keep components as functional components whenever possible. Let's dive into the evolution of React patterns and how we can share component logic.
Welcome everyone to this workshop about incrementally adopting modern React patterns in a legacy codebase. I'm a software engineering coach and currently a principal engineer at Sainsburys. I've worked on various projects and have experience in training developers. Let's get started.
3. React Hooks and Legacy Code
Functional composition with React components can be achieved through higher-order components and the RenderProps pattern. Hooks allow for composition perpendicular to the tree, enabling the reuse of custom hooks and the use of side effects. When faced with a legacy codebase using class components, refactoring everything to hooks may not be viable due to large codebases, complex logic, and time constraints. Balancing code quality with delivery is crucial. Hooks can only be used in functional components, and following this rule is essential. To address this situation, we can start by examining the error and identifying logical side effects in our custom hook that we want to reuse.
So in that way, you are essentially doing like functional composition, but with React components. And what you can do is pass them things via props because components get things from the outside by props, or at least they did in the old world. That was the way that they got them. So that's where higher-order components came from.
Obviously, you've probably seen quite a few high-order components, like Connect being a very famous one with Redux, like, that also like with Router from React, Router is another very well-known high-order component as well from the libraries. So it was very…all of this sort of React ecosystem very much like adopted that pattern as well, like as a way to share stateful logic or component logic, maybe is a better way of saying it.
And then, yeah, going forward in time a bit further, we got this idea of the RenderProps pattern which allowed us to make our composition a bit more declarative and essentially do our composition at render time. So the way that that works, just following on from the higher-order components is you actually only need some sort of dependencies, like when a component actually renders. And in React, you've got this composition model where you can pass down children. We'll see code examples of this later, so don't worry if you're thinking this sounds a bit abstract.
But you can, you know, you can have a function as a child. So, as you can see on this graphic on the left, it's like you've got some React component and you say, okay, my children are a function, that function can be invoked from whoever this parent is with some arguments, and then in the parameters here, you can pull off whatever it is you need and just return some more components. And you sort of got, like, the things that you need at render time, which is cool. And so, yeah, this was something that really gained a lot of momentum. Again, it's a pattern that's still around, and it's also a pattern that's still used quite a lot. It's really relevant. That's why I'm sort of talking about all of these things. This one is still very much, you know, on a day-to-day, you'll see it around. Hire all the components less so that we'll have a look at why that is in the examples too.
And then, finally, this latest evolution, which I'm sure you're all aware of because it's been, I think, a couple of years now, the hooks came about. And what React Hooks allowed us to do was essentially do this composition perpendicular to the tree. I really like this way of thinking about it, because it really helps actually, by the way, always to think of your components, your whole application really as a tree structure. And in that way, you can reason about, like, who's the parent, who are the children. And, you know, change of state or props and apparent is what triggers the children to re-render. So it's always worth thinking in this kind of way, like in the tree, like what is the hierarchy? But yeah, essentially hooks, what it does is instead of having to do it vertically, which both the other patterns do, you can do it horizontally, because you can just write a piece of component logic and then you can just hook into that piece of component logic from any component anywhere in the tree. That's sort of the big idea. So yeah, hopefully that makes sense, but we will see some more.
So if we are using functional components and we want to, yeah, like reuse some sort of, in this case, a side effect, useDocumentTitle, then we can quite simply just use it. So you see on the left-hand side, function here, calling it useDocumentTitle. So it's a hook, takes in a title, and then it just runs this effect, right? So, the usedEffect hook, everything that's a side effect should use that for, and in this case, obviously, using this document API is a side effect. So just run that and then, yeah, inside any given component, you would just import useDocumentTitle and pass it that string which is the title it's expecting. Simple as that.
But then, yeah, you're probably thinking, what if I hook returns something? Well, yes, good question. So, if the hook returns something, so just building on that same example here, you can see at the top here a custom hook which takes in the title as an argument, and it also returns an update function and the current count. So, just adding a little bit of state into the equation here, like inside this custom hook. And yeah, what it's going to do in that useEffect is just run the effect there and then print out the count and title, so we would see that in the top of the document. And from the hook, there we're returning an object with two different things, like the current count itself, and also the update function which is the set counter, which we defined up at the top of the useState. And then, yeah, if we wanted to use that custom hook in a functional component, very simple, yeah, there might be some functional component called document.titleEffectFnComponent, and all we need to do is just use our ES6 deconstructing here to define two variables, count and setCount, because we know that's what's returned from that object, and then pass in our argument as well. So in this case, we've also passed in an object with like title, hey. Yeah, hopefully that all makes sense. This is pretty sort of like one-on-one stuff at the moment for hooks, but we're building up. So, cool, so, yeah, I guess, leading on from this, what do you do, though, when you've got like a nice, custom hook, like the one we just saw, and you're like, oh, that's so cool, I can change my documentite. I'm not sure if you'd want to, but you might. But all your components are class components. You're like in this world where it's a legacy code base. Yeah, firstly you might say, well, I could refactor everything to hooks, but that might not be viable for various reasons, right? Because your components might be really large and hard to refactor. There might be a lot of complex logic. It also might be sort of really well tested, and you don't have time to rewrite the tests. It might simply come down to the fact as well that this thing about time is really interesting because it's like, what's the relative benefit of the refactor? And that's one of the things that we have to judge because we have to sort of, I guess, weigh that against delivery. Like if you need to deliver new features, then you need to deliver new features. And obviously you can write anything new using sort of the new syntax and everything, assuming that you've updated your version of React, which you should because it has great backwards compatibility but yeah. I mean, you might have this situation. Certainly where I work, being a 160 year old company, nothing about legacy code and like, yeah, like sometimes there's gonna be like co-based as well. That just hasn't been possible in maybe part of the co-based and maybe part of it started to move. So that's what we're gonna get into now. So what kind of happens, I guess, is the first question. Like when we try to use hooks in the class component, maybe some of you have tried, but I will tell you, you basically get an error saying, can only be called in a functional component. Error message looks like that. So yeah, it does tell you what the problem is. This is obviously sort of one of the rules of hooks. I do recommend, you know, like working with hooks, just generally like, definitely read those because it makes all of the errors that you can't make a lot more sense. There are actually that sort of links in the slides. The slides will be shared at the end, so you can click on any of the links directly. I'll also post them all in the Discord channel. I'll open up some of them, but probably not this one as just the React documentation. So yeah, when we're faced with this situation, we need a way forward that balances codary factors with delivery. That's normally the reason why this sort of thing comes around. So yeah, what we could do then in order to start solving this is start by following the error. So some logical side effects in our custom hook that we wanna reuse. We'll start with that.
4. Using Hooks and Patterns
When using hooks inside a class component, create a functional component that wraps the hook and passes down props. If the hook doesn't return anything, simply wrap it in a functional component and pass down props. If the hook does return something, consider using the render props pattern or the higher-order component pattern. The preference is to refactor to hooks first, followed by render props, and then higher-order components. When using render props, wrap the hook inside a functional component and invoke the children as a function. Ship the hook as a named export and import it into class components as needed.
So we can say, do I use document title? So if we want to use this inside a class component, React wants us to only call hooks in a function. So if it's not really returning anything, the hook, all you need to do is just wrap it in one, right? I mean, when I say a function, I mean a functional component. So all you need to do is create a component called document title. And then that will expect to take some props from whoever is using the component. And then you can just call the hook inside that component with the title and just return null and that will get it going. So if you look at the image in the bottom right-hand side, now we can use this as a normal component and just pass the prop. So in some class, in some dashboard, there's a bunch of stuff that you can't change, but yeah, you can just use your document title and you can reuse that all over the place now, which is cool. But yeah, like, let's look at the case that our component, if our hook actually returns something, which we saw our hook returning something just a second ago. So then it sort of gets a little bit more complex because if it's the case that it doesn't, then it's really easy. You just wrap it in a functional component and just pass down props. But if not, then we sort of need to implement one of what I'm gonna call here the historical React patterns, although of course, they're not really history. We're still sort of with them, they're still around because they both work with class components. Like, we know that they work, we've been seeing it. So we kind of got a couple of options then. We can go for using the render props pattern and we can inject our dependencies by invoking them as arguments. Or we can go for higher-order component pattern and get our dependencies via props. And again, which one you sort of go for, it depends on the requirements. Like, I would say, though, my preference would always go first try and refactor what you have to, like, hooks if you can, if it's simple enough, like, sort of go for that. And then just, you know, you just use your custom hooks if that's what you want to do, followed by render props, which is why I put it first, if you can. And then I guess the higher-order component one would be the last one. But yeah, we'll see an example now of like how we can do all of these. And we'll also see when you're building a custom hook, how you can think about the fact that other people who are using your hook might be in this position. So essentially you can ship it with a render props version and a higher-order component version. And that just gives the flexibility to whoever's using it, basically, like other developers in your code base. But yeah, we'll get onto that in a second.
5. Code Structure and Functional Component
Inside the code base, the exercises are organized into different folders. We start with a functional component that uses the useDocumentTitle hook. We then explore using the same hook in a renderProps component. Next, we discuss using higher order components instead of renderProps. The higher order component takes a component as an argument and returns another component. Inside the wrapped component, we can use our hook and pass down the necessary props. Let's go back to the slides and explore the higher order component example.
So just quickly about the code base in terms of the structure. Oops, not that one. Inside the src folder, basically the exercises are just all in different folders. So you can just work in side the one that you need. And then, yeah, I mean, the entry point is over here, index.js. The next component down in the tree is app.js. And then all of them are sort of, as you can see, exercise one to exercise context.
And so what we're looking at now is this functional component here. So I'm gonna show you inside the example, the functional component, and I've sort of tried to name them what they are to just try and help. But obviously, in a real project, you probably wouldn't lay it out like this, etc. So yeah, this example that we're looking at now is the functional component itself. So it's very simple, right? We are just pulling off the things that we need. So if we have a look at useDocumentTitle, here's the hook itself, same thing that we just saw on the slides. And then yeah, inside a functional component, you just use it like this, super simple. So let's just check it work, so I changed this to hello or something. We should see that like that update, there you go, ran the effect, updated, says hello at the top, wonderful. And yeah, if I reload this page as well, it's gonna just reset the count back to zero because that piece of state will not persist between renders. So yeah, very simple for the functional component. Let's have a look at how we would do that inside our renderProps component, which is what we just saw. So that's the functional component. I'm just gonna comment it out and just get this one going. So in the renderProps component, this is now, as you can see, let me make that bigger. As you can see, this is inside a class. So now it's this situation where, yeah, there might be some sort of class stuff going on here, some sort of logic, some stuff you can't refactor. And what you can't do now is this, right? Like if I try to do this bit of code here, which is what I was doing in the functional component, like that's not gonna work. You're gonna see that error like, oh, you have to be inside a bunch of components. So yeah, just as we saw on the slides. Implement this useTitle effect, passing it a prop of whatever we want the title to be. And then we can pull off what the count and the setCount is. So I'm going to just change this so you can see that it is working. And with this one, it looks slightly different. I've just pulled off here, as you can see like the count there. And at the top, notice here the document title, which is what the hook is doing. It's like zero and it says new title, which is what you passed in. And the counter is in fact working, and I'm pulling there the count as well. So yeah, because what we were talking about before, you've got the update function. So you can call that here, and you've also got like the count itself, which means if you want to, you can put the count there. Yeah, hopefully that'll make sense as an example, but you can see that's how we were sort of go about doing this with the render props. Cool, let's go back to the slides. And I will talk to you about the higher order component as well and I'll show you the example. But of course, as you can probably imagine, you're gonna get to practice this as well. So like what we just saw, you will get to practice your very own with something that maybe is a bit more of a kind of use case that you might actually have. Cause you may be thinking like, oh this thing with the counter is a bit kind of contrived. That's true, but the thing is, is simple. So it's easy to sort of reason about. Cool, let's talk about using higher order components instead of the render props.
6. Reusing Component Logic with Hooks
We pass the dependencies via props and wrap the class component with the higher order component. The wrapped component receives the dependencies as props. The higher order component adds the necessary props to the class component. We can see the hook in action and how it affects the document title and count. We have explored three ways to reuse component logic and run side effects using hooks.
We just like doing a bit of prop drilling there and then we will pass any other props. And yeah, again, you will want to basically just export this thing out of here as a names export or something like that. So you can use it in another component.
So then on the other side, in a class component that we can't refactor. Now, when we want to get these dependencies are coming via props. What we do, and I'm sure you've all seen this before is you wrap the component with the higher order component, because remember it's a function that's taking a component as an argument.
So this is the function we've used title effect HOC and we pass it this component here. And now what that's gonna do is basically get some new stuff on our props because that's what we did. So now if you console log like what are these props coming into this class component? You're gonna have like a count on there and a title and also a set count because we decided to add those things. And yeah, they will just show up on your props in the same way that all sorts of other stuff like history location and match will show up on your props if you use the with brouhaha higher order component inside your project. Assuming you've got a router, a top level router. But yeah, let's have a look at this one in action as well quickly. Let me show you.
So yeah, in here, let's just go here and activate the higher order component. I'm gonna show you how it works. So here we've got this title and remember that's the thing it's passed down now from this sort of top level because the higher the component, this thing is gonna be the wrapped component essentially. So if we go into that higher order component, let me just do this so you can see it better, down the bottom here, we are wrapping it. So yeah, we've imported it from that used document title. We're wrapping it. That's what we just saw. And now we can deconstruct these because they're gonna show up on are these stock props. Yeah, if you're operating in a class, of course, don't forget the, this, that's super fun and moving between classes and functional components, stuff like that. And then let's have a quick look then how we implemented that. So inside our custom hook, what we did is this, which we just saw as well. So here's how we defined it, takes components and argument. Yeah, it's expecting to get a title. You just saw that as a prop and then yeah, we will have the count and the set count just passes them all down in the same way. And then we export all of them out of the bottom of here. And then now if I go back here, as you can see, it's like the document title is something. You can see that up there at the top of the screen. And you can see here, I'm also in this one just for clarity, I've got the count going on here as well. And also like what's the current document title? I click it, it goes up and you can see that up here as well, top of the screen. So yeah, looks like it's also working. So what we've done there is basically, yeah, just three different ways now that we have reusing this component logic and running that side effect all sort of via the hook.
7. Refactoring Class Component to Hooks
If you can refactor your component into a functional component and use hooks, then go for it. Create a custom hook if you want to reuse component logic. However, don't jump ahead to making everything into a custom hook if it's not necessary. If you want to use the custom hook across projects, you can publish it on NPM or github packages. If you have functional components that you want to share, consider implementing render props as well. Exercise one involves refactoring a class component to hooks. The code should only be executed on the first render.
Cool, let's go back to the slides. By the way, that example will come in very handy. It's in the example folder. Just like the branch I'm looking at is the main branch, of course, it's not some sort of solution branch or something like that, but yeah, you have those examples. So definitely like check it out when you're doing the exercise because it will help you go in the right direction.
So yeah, let's have a quick look at the exercise. I'll just show you quickly what the exercise is. And then we just do some questions now before you start. And then when you start, I will put you into the breakout rooms and things. So and that will be after that comfort break that's coming next. But let's have a quick look at what the exercise is. So when this thing is running, I've also put like all of the texts for sort of what you need to do. That's also in the read me of the repo. So if you've broken the app and you were wondering like what you're working on, I do recommend to just look at the read me cause it's there as well. That's over here. That's the link that hopefully you all got. It's in the discord. So yeah, exercise one is pretty simple. Like what we want to do here is refactor this random image JSX using the use data and use effect hooks and this is like the first thing we said that we should do is like, if we can just refactor from a class component to hooks, then we should just go ahead and do that. Like, if it's simple case, so this one should be pretty easy. So I'm not gonna give you like super long for it. It's the most trivial one, but I think that should always be our first political. So it's worth like practicing that. It should only be executed on the first render. So like when you reload, you should see a new image. So like when I reload this, I see a new image. There we go. The API is working. So let me just show you the code for this now, which you're gonna refactor to being a hook. So if we go into this folder, close the example, go into exercise one, this is the index here you can see this is a random image component. That's what's being rendered below the instructions. And then this is the random image itself. So in this one, yeah, your only task really is just like get rid of this class syntax.
8. Introduction to Exercises
I've provided some inputs for you to refactor into hooks. It hits the Rick and Morty API, retrieves a random image, and sets it as the source. Error handling and loading handling will be covered in the next exercise.
And yeah, I've even done some inputs for you and stuff and stuff like you need to use state and use that effect because you will need to run an effect there. And you should just be able to hopefully fairly rapidly refactor this into hooks and it should just work exactly the same way. Yeah, it's pretty straightforward to be honest. But yeah, all it's doing in case you're wondering it's just like hitting this Rick and Morty API, which is fun. And then just getting back some response and I'm just randomizing it and then just setting it to say like a random image, that's all. If you're thinking like, oh, there's no error handling and all the rest of it and loading handling. Yeah, wait for it because we'll get there in a second one. This is supposed to sort of be really trivial. So I just didn't wanna put sort of more craft inside this exercise, but in the next one, I sort of, you'll see some of that's been done for you inside the hook itself because yeah, just helps with sort of a bit more of a realistic exercise. So yeah, this one is pretty much it for the first one and let me show you, well, we're here the second exercise as well.
9. Implementing Use Random Image Hook
The second exercise involves refactoring functional components JSX in exercise two to implement the use random image hook and display the image with the image component. There's also a function to implement a button for fetching a new random image. The exercise provides code comments and the use random image hook is already done. The exercise focuses on implementing different components and handling loading states and errors. The exercise also includes tasks for implementing the same functionality using render props and a higher-order component.
So with the second exercise there's sort of a couple of parts to this. The first part of that exercise is just a refactor functional components JSX in exercise two to implement the use random image hook and display the image with the image component. That image component is already important and stuff where you just need to pass it like the image URLs, SRC prop and yeah, it should pop up here. It won't be that size. It would probably be this size. But yeah, once you got it going, that should work fine. And then also there's a function in there which you should be able to pass and implement like a button. And when you click it, we want to like do a new random image. So it's slightly more complex than this one, not on reload, but I want to have like a button where I can sort of get a new random image because maybe that's what I've been asked for. So let me show you quickly exercise two. So inside the functional components, this is the functional component here, which is sort of the first part. Yeah. What you'll need to do is use your hook here. I mean, this is a function component so it should be pretty straightforward. I've done the import for you already. And then yeah, down here you can just use image and also implement the button and feel free to remove the box if you want to. And yeah, with all of these, there's like kind of code comments around, definitely read them if they're there, but feel free to delete them as well. And what I've done for like all three of these as well is your use random image has been done for you already. So that's what I was mentioning a second ago that this is sort of like a little bit more of a fleshed out version. Obviously there's more refactors that could be done, but yeah, just trying to balance sort of getting a real issue example of keeping it simple. So in here, this time we do do some loading stuff. We have like some loading states and error state. You don't really need to worry about any of that stuff because your sort of big task is to do this, right? To implement like these different things. So for the first one, all you need to do is actually just use the default export, which is just use random image. You just need to like look at this. Reason about it a little bit, see look at the things which are returned and just get it going. And actually, yeah, I was thinking to get you all to implement that toggle function as well, but in the end I decided to just like leave that in. So I've sort of done that for you as well. So just have a little browse, I guess, of like what's going on here. But essentially it's the same thing. We've just sort of implemented some loading states and we've just made sure that like we do some error handling as well. And that's something that definitely when you're doing like hitting an API, like a rest API with like a hook. Like you probably want to do this, right. Because whoever's using this custom hook it's like when it's like loading, you probably want to show a spinner and like if there's an error you might want to show some feedback UI. So that's why all of that's there. And that toggle is just gonna help you with the reload. But feel free to change the name of that, actually. Probably Re-fetch is a better name than toggle. And yeah, that's pretty much it for the exercise two. And then going on from there so as you probably can imagine, the two other parts of this exercise are the, like firstly do that, but with a render props component. So what you want to do is like, look at the example and then look at this hook and try to like get that going using render props. So you'll need to do some coding in this zone here and then the same thing for the higher-order component. And yeah, you've got some more code comments down here for the different tasks that you need to do. But essentially all of those components are already being rendered. So you can see them here on the screen. So like, you don't need to worry about commenting or uncommenting components once they're working, they, once you get them working, they should just be working. So if you look at the one with friend of props, for example, I've done the imports for you. I've even imported a spinner and the button look, which you may, or may not want to use. You are going to need to import that component that you had. And then, you know, down here is where you're going to need to use the return from your hook and pass it like the images I see. And then the reload button and things. So yeah, hopefully that'll make sense. So essentially, very similar to the examples exercise for these exercises, it's just a case of, yeah, check out how we did it in the example and try to get those going. If you want to like skip exercise one, you can, I guess, but yeah, I'll just like give you all like, maybe like 15 minutes or something for exercise one, but if you want to get started on exercise two, feel free. After 15 minutes, we'll just like wash up exercise one because that one's hopefully just like more like a warmup. Yeah, I think that that's pretty much it for this part and we will talk about this later. So I guess my question is, are there any questions at this stage?
10. Introduction to the Workshop
Not at this point? Not at this point. Yeah, I guess there was a lot of information to assimilate there. Many things quickly, yeah. But definitely, yeah, have a look. Hopefully like look at the example. We'll do like a refresher after the exercise and go through the whole thing as well. But yeah, if you have any questions while you're doing it, just.
Not at this point? Not at this point. Yeah, I guess there was a lot of information to assimilate there. Many things quickly, yeah. But definitely, yeah, have a look. Hopefully like look at the example. We'll do like a refresher after the exercise and go through the whole thing as well. But yeah, if you have any questions while you're doing it, just.
The rendered props it's something that I kind of understand, but it's maybe after the exercise, it will be more clear, and maybe you can go over the solution with it. Yeah, absolutely. Yeah, that's the idea. My big recommendation with the exercises reference the example, because it's gonna really help a lot with that. Like see how we were doing it there, have a play with the codes. And yeah, cool. Well, I'll let you do the first one for like for 15 minutes or so, and then I'll just show you the answer to the first one. And then I'll give you for like the second one, we'll probably do like 45 minutes or something, because there's several parts. And we can do the breakout groups. I guess I would say, yeah, for this first one, because it's just like 10 minutes. We won't do the breakout groups, and that's, yeah, yeah, it's just like 10 or 15 minutes. Let's just stay in the main group. So yeah, I'll be here, so feel free to ask me any questions. And I will show you the answer to the first one in, I don't know, I guess we can say at like 5pm in 10 minutes or so time. And then we'll move on, cool. But any questions now, feel free to just shout out. I'll be here, please start. Just wait for me.
11. Refactoring to Functional Component and Hooks
Just refactor Exercise 1 from a class component to a functional component. In the render property version, you can directly pass the hook's return value to the children function. Hooks like useState and useEffect return arrays for convenience and to avoid verbosity. Hooks can return any value, but they must start with the 'use' word. React checks this before turning it into a hook. React's backwards compatibility allows for incremental adoption of new features. Upgrading React versions is usually straightforward, but be mindful of library compatibility. Frameworks like Next.js provide convenience but may have slower updates for sub-libraries.
Just wait for me. Yeah, hi Richard. Thanks for that. I'm sorry I came a bit late to the session, but I just wanted to check. Did you want us to make that into a functional component, random image? Yeah, exactly, that's right, yeah. Okay. So for Exercise 1 all you need to do is just, it's a class component right now. So just refactor that into being a functional component. And that's, yeah, that's all. Okay, thank you. No worries.
Hi Richard, I have another question. In the example for the render property version, you first destruct what the hoop returns and then construct the object again when you call children. Is there any particular reason you couldn't just directly pass whatever the hoop returns to the children? Yeah, good question. The answer is no, you could totally do that. It's just that, I just find it easier to sort of put things in an object and then deconstruct them on the other side. Cause then if you need to add more, it's really trivial to add more things. And then it also doesn't matter the order of the parameters. Then if you think about it, the order would matter if you didn't do that. Like if you got the wrong order, it would make a difference, but otherwise, no. Yeah, I'm not talking about like, not making it into an object again for children. But I could see where you would just do like props is use title effect and then pass that props object to the children function. So nothing would really change. It's just that you're not destructing and then constructing again. And the one of the, maybe you'd need to do this because even though count, assert count wouldn't change between updates, the object as a whole might, but I'm actually not sure about it. Yeah, that's true. I mean, yeah, there are options here. I mean, we don't have to necessarily sort of do it this way. I just, yeah, I guess the reason it's like, like this in the example is, well, essentially the extendability aspect, I guess. That would be my main reason for like doing it that way. But yeah, you absolutely, and another interesting thing about this as well, if you've only got two things, like if you think about it inside your custom hook, you could also have those as an array if you wanted to. Like it's up to you what your hook returns. But I find like nine out of 10 times that my hooks tend to return objects because yeah, you tend to add to it right over time. You're like, Oh, now I need to know this extra thing. Now I need to earn this like, but this is clearly an object rather than an array. But yeah, in these cases where there's two, there's a good argument to be made for like, Oh, that's pretty simple. Thanks. All right.
Yeah. The main reason why the main hooks like useState, useEffect are returning arrays. I actually read about it for a bit. Dan Ebermoth, I think wrote about it. And the main reason was that you probably use a lot of useState in one component, like you could use multiple of them or you can use useReducer. You can use all these hooks multiple times. And if they were to do it with an object, you would, it would kind of get really verbose. You could have useState and that would return state and a setter. So you'd have to rename it every time because you're using it multiple times. And if you're doing it in an array, you don't have to do that every time. So it's just easier in that way. But yeah, your hook can definitely return whatever you want. There's no rules on it, for that matter. Yeah, apart from the hooks rules, there's only one more rule and that's that your hook should start with the use word. That's right. So internally, React does actually check if it starts with use before it actually turns it into a hook. Yeah, absolutely and speaking of that, I'll post the rules of hooks in the Discovery, so that is just for reference, but yeah, good shout. That sort of is a really, definitely, that is very well documented React. And the other thing as well, which is cool, is the backwards compatibility. Because unlike Angular, they didn't break everything at some time. Like your class syntax will still work. You might get some warnings sometimes about deprecated methods and stuff, but like you can pretty confidently update the newest version of React at a given time, which is great. And that's what gives us this ability to incrementally adopt things instead of like a big bang change, which is cool. Yeah, definitely, you can upgrade from like version 14 to 17 without doing much. The main issue would be your libraries, which would probably break by the time, but React itself is pretty much still the same, yeah. Exactly. Yeah, I agree. The only thing that can sometimes... Yeah, one thing I guess I would say that could slow you down is like, and this is the thing about sort of when you get to frameworks versus libraries, where it's like this idea of convention versus configuration. Like the more, you know, if you tie yourself to something, I don't know, let's say like Next.js, whatever, like that's cool. You're gonna get stuff done, but then you're tied into that. And so they might not update a given like sub-library as fast as you might like.
12. React Evolution and Refactoring to Hooks
React has come a long way since 2014, with improvements in developer experience and error messages. Create React App and ESLint provide helpful tools and error messages. The developer experience is excellent, with relevant error messages and component-specific error details. Refactoring from class components to functional components is recommended, and leaving the original code intact is beneficial. Introducing state with hooks is straightforward, using the useState hook. The useEffect hook allows for running side effects once when the component mounts.
That happened with React rather a while ago with like version four. It just took them a while to sort of do it. So you'll be sort of stuck using like an old API. Whereas if you do it sort of more vanilla, you've got like the flexibility, but then yeah, it's on you to keep everything going. So yeah, it just, you know, sacrifice a little bit of speed for some more sort of like flexibility.
Yeah. It also really depends on like what you want from the framework, you know? Cause React itself doesn't care about anything other than rendering stuff. So if you use a Django API or you use the cloud like a cloud functions or whatever, it doesn't care at all. As long as you feed the data, it's going to render HTML. And Next.js and other frameworks like Blitz, I think, and whatever, there are a lot more opinionated because you have to use their tools, which, well, as you said, it saves you a lot of time, you know, because everything works out of the box, everything's integrated into each other. If you look at code splitting, for example, in Next.js it just works out of the box. If you use create React app or anything that is not as integrated, you're going to have a hard time to implement it properly. So yeah, it's definitely a bit more like, do you want everything to work out of the box or do you want to build your own stack in that kind of way? Both are fine, really. The only upside, I think, in using things like Next.js, apart from that it's a lot faster, is that everything is documented. So if you have another teammate coming in and they're going to help you, and if you're using Next.js they know what they're going to expect, because it's all the same. Whereas if you build your own stack, you're going to have to teach them how it works and you're going to tell them everything you're using. Yeah, there's definitely upsides to both of them.
Yeah, absolutely, I agree. Yeah, for the hooks rules, I actually forget about them every day, I think. Because the ESLint rule just takes care of it. You read it and you go like, all right, that's some rules I gotta adhere to. And then you forget it, and it's fine, because ESLint either fixes it for you or just crashes your whole app until you fix it yourself. So, yeah, there's definitely helpers for that. Yeah, for sure. It's good. It's actually, they're very good as well the error messages. That's something we'll actually see later in a lot of part of this presentation about like custom hooks when you're building your own, it's like, how can you give a good developer experience? Like, how can you give a relevant error message? We'll see it in a bit. Yeah. Definitely worth doing. Yeah, even in production, you get a really small error message, but they always add like a link to the documentation with that specific code and you can open and then explain what it is. Yeah. And definitely if you have your resource maps set up, I think Create React app does it by default, they actually tell you what component is breaking. So you can just look at the error to see what's going on. Yeah, exactly. It's great. Yeah, it's very, the developer experience is very good. It's definitely, yeah, I've been working with React since 2014 and yeah, it's come on like a long way in terms of how it is like, like that, yeah. I mean, even stuff like, I mean back then there was no Create React app, even like it was, this joke of like, it's to get it started, like it would feel what pack comes things. Things are great. Back then I had to use a Gl man. I think it's one of those generators and they had a ton of these presets. And I think I took more time to actually find one preset that worked for me than building the app, because there were hundreds of different of them and you could build your own webpack on thing and you spend a week to learn webback only to break down and you in the next version. And then you'd add a loader and it wouldn't work specifically for your project. So it would die again. And definitely the error messages, it was a hard, because your REP app would just break and you'd ask React, what's going on? And it would just say, I don't know. Nobody knew what was going on. You just had to find it. And now it actually tells you what's wrong. So that's a lot better. Ah, yeah. Yeah, definitely. Cool. Hopefully you've all had a fun with the first one. Let me just show you the answer quickly to the first one, because hopefully it was fairly straightforward. Yeah, so here's the application. So I've made that re-factor and I can just do, the counter still looks like it's working. Still like working at the top of the screen, there in our tab. Let me show you how that looks. So one of the things with this, that I don't know how many of you did this, but I definitely recommend to like leave the original when you're re-factoring from a class component to a functional component. It's definitely worth leaving it rather than deleting the whole thing. Hopefully most of you did that. But yeah, essentially we needed to introduce some state, right, with the hooks. Like the imageURL, said imageURL. Needed both of those. This function could pretty much stay the same. So I just left it that way for this. And then, yeah, just need to use the set imageURL instead of using the this.setimageURL or whatever it was before. And we said that we just want it to run one time when the component mounts. And so the way to do that is, in your useEffect hook, you can run the side effect and you can just pass it an empty array. That's the dependency array.
13. Refactoring and Implementing Image Loading
In this exercise, we need to make some changes to the code to ensure it runs properly. There are a few things to consider, such as setting the image URL correctly and managing state. We can discuss different approaches, like using the useEffect hook and managing state with useReducer. If you have any questions, feel free to ask. Moving on to exercise two, we'll be implementing a loading state and exploring different ways to handle asynchronous functions. I'll visit each breakout room to assist you. Once you have it working, you should be able to reload the image by clicking a button.
So it will run every time something in that dependency array changes. But in this case, yeah, we just want it to run on mount. So when the component, if I reload the page. Well, having said that it's working, actually, it looks like it's not working, but yeah, essentially. Because of the image, because you have a component that calls image and you are using the image itself. If you put up, you have a component or not. At least the previous one, you have it. Oh, yeah, yeah. It didn't do a very good job with my. From share to react. Isn't it because of the object that you're setting with the setter for the state? Because now you have to set it straightaway to the variable. Yes, indeed. This is what happens. Also that. Yeah, I've been there, done that. So that's why I cut it. Let's do, it's gonna be probably character.imageURL or something. Just the image. Yeah, yeah. I think it's working now, looks like it. Oh, oh no, it's not working. Just the image? Thank you. I guess you all did it. So that's great. Faster than me, too. Yeah, I was getting distracted. But yeah, cool. So does that make sense to everybody, those things? Hopefully this one was fairly trivial to sort out. But yeah, just a few things to sort of change around. Any questions before we move on to the second one?
Yeah, Richard? Yeah. Can you put the fetch random image function, let me see, sorry, I've done it slightly different to you. It's okay, as long as it works. You could put all of this stuff directly in the user effect if that was all of this stuff. Yeah, absolutely. Yeah, yeah, yeah. Yeah, same thing. Okay, thanks. That's fine. I mean, this is some stuff to take a decision on. I mean, in part two, that's where it gets a bit, you'll see, in fact, that's exactly what we do in here. So yeah, moving on to part two. If you look at our user random image JSX here, yeah, in fact we do do it here because we want to, like, have our loading state stuff going on. And yeah, we basically just define the async function inside the user effect itself and then we just call it here at the bottom on 28. Yeah, it's an easier way to do it. But yeah, I mean, there are different ways to do this. So there's no sort of orthodoxy about how to go about doing it. Same thing goes for maybe some of you are thinking about, like, yeah, getting too much state here could probably manage this with, like, a use reduce, user reducer or something instead. Absolutely. I do agree. But yeah, I just wanted to not do that in this particular case. But yeah, once that starts to happen, that's something that you can reach for as well, just to help you, like, manage state within here. Make it so that you don't get into like a muddle. Cool. Does anyone have any questions about exercise two or exercise one, which you just finished?
I just had a short question regarding exercise one, can you open the console? Just, I don't know, I thought maybe we should check if there are no errors. Sure. Perfect. Just used to always check the console from my side, that's why I was asking if it's possible. Thanks. Oh, for sure. Yeah, no worries. Yeah. Cool. Nice. So yeah, in a second I'll put you all into the breakout room so you can have a crack at this cause it will take a bit longer, but I guess what I'll do is sort of come around and visit each of those rooms in turn and like see how you're getting on. Probably some of you have started exercise two already cause yeah, you probably finished this one, but yeah, if there's any other questions about the kind of purpose of exercise two, I guess, yeah, feel free to ask now. Otherwise I'll come around and help you out inside the group. I guess not. Well, anyway, once you get it going, then you should be able to sort of have this effect that you can see now, something like that, where I click to reload and I can get a new image. Very handy. Cool, all right.
14. Breakout Rooms and Integrations
We used breakout rooms for the workshop, which proved to be a useful feature. Zoom has done a great job in handling large webinars and keeping their platform up to date. Slack's video function is not reliable, and Slack itself is not meant for screen sharing or meetings. Integrating Zoom with Slack and Google Calendar can provide better options. We will now have a quick wash-up of the previous exercise and then take a five-minute break before moving on to the next part of the presentation. If you have any further questions, feel free to ask.
So I'm just going to stop sharing for now and I will put you all in the breakout rooms. Hello, everyone. Welcome back. We'll just wait for everybody else to come back. I think they'll automatically be popped in here in a minute. Yeah, that was our cue to go back as well. We got the notification. You got one minute to go back or we'll make you. So, okay, okay, I'll go back. Yeah, exactly, it sort of pushes you around. That's a bit of classroom management there, isn't it? From Zoom. Yeah, yeah, but the breakout rooms are really useful. I didn't even know they existed for a long time. It's a really good feature, yeah. Yeah. Like yesterday, I figured out there's apparently a webinar function in Zoom, I didn't know that either. So, it's pretty cool. And it can handle quite a bit. I mean, we had almost 500 people on the webinar in our company, and it was perfectly fine. It was just, no problems. Yeah. They've done a good job, I think, with keeping it really up to date. Especially with everybody jumped on Zoom as a company. And yeah, I think they've handled it pretty well, to be honest. I mean, they'd been around a while, so they should. But even so, it's good stuff. It's definitely better than MS Teams and other such things. And Slack, the video, is just horrible. Yeah, it's the worst. Yeah. Whenever I start screen sharing, Slack just decides to, you know, just break. It dies. Yeah, it's definitely, yeah. Can I ask, is there any alternative solution? Because I see that Slack, for this monitoring and this controlling GitLab comments things, not working, I think it's a great tool for that. It's not meant to be for screen sharing or meeting, right, I don't know. Yeah, no, you're right. I mean, I guess they just started doing it and I don't know, where I work they've got like a video version of Slack, but it just falls over when there's too many people and things happen, they're still figuring that out. But you have a good integration with Zoom. So we actually, when we hit the two, when you hit any call on Slack, we go to Zoom. Oh, cool. Yeah, so yeah, it's an option to get it. And it's much better, yeah. We did find that you can integrate Zoom with Google Calendar. So that instead of Google Meet, it starts adding Zoom links, because that's a lot better as well. But you get like, when you create a meeting in Google, that you use this use Google Meet, that you integrate the use too? Yeah, that's like the default, you know, you have the Meet links inside your calendar events. But there is a way to get Zoom links in there. I'm not sure how, because someone did it for us. But it should be possible, yeah. Cool, cool. Nice, I think everybody has come back now. Hard to tell, but anyway, what we'll do now is just a quick wash-up of this one. So I'll just show you a couple of things, and then, yeah, any further questions. I visited, I think, all of the groups though. So it looks good, I know most of you have done it. So keep this one fairly brief. And then, yeah, we'll probably take like a five minute break and then we'll do the next part of the presentation. So let me just share my screen once again. Alright, cool, so if you got it going, you probably have something along these lines. So this was like our first one, which was just the, yeah, if I click to reload, it reloads. Same thing with the render props one and same thing with the high roller component. You might have seen that loading spinner flash there as well. That was some little bonus. If you slow down the network, you can observe some loading spinner action. Show you what I mean. Maybe, oh, there you go. Well, maybe you saw, maybe not. But anyway, I'm gonna just turn that off. Fast3G, no throttling. Cool, so how did we do this in the code? Let's have a quick look at that, or at least like how you might've done. There's no sort of hard and fast.
15. Using Hooks and Render Props
Let's start by looking at the hook itself. Using the hook in a functional component is straightforward. Import the hook and destructure the returns. Add loading and error handling. Now, let's explore the implementation of the render props. Create a functional component and destructure the children prop. Return the children function with the necessary arguments. In the class component, import the component and pass it as a child. Build the logic inside the function and return the necessary values. Handle loading, error, and toggle before the return. Any questions about the implementation of render props? Let's move on to higher order components.
There was a few different ways of sort of going about doing this, but let's start over here. I guess it makes sense to just have a look at this, the hook itself. So yeah, this was sort of already set up for you, including this toggle function. Maybe you sort of changed the name of that. I know a few of you also played around with some other refactors here where you sort of experimented with moving this async function out and sort of calling it directly. That's great, definitely something you can go for as well. It all just depends how you wanna do it.
So yeah, it's sort of exposed those things, right. So in terms of using it inside a functional component, should be quite straightforward. Essentially, we're just doing it here in this one. So you've got the image, you've got the button. I'm just passing the toggle function to the button and what I did is just imported. It was the default export, right, so I just imported it up here. Did our deconstruction there of the returns from the hook. And then, yeah, it's very nice as well, being inside a functional component you can do this kind of thing, you can add some loading state, just some early returns, same thing with the error. Probably would do something else there as well, just let the user know what's going on. So that's the functional one, hopefully that sort of makes sense, it's the sort of standard hooks, very clean, very nice.
16. Using Higher Order Components and Render Props
To reuse component logic inside a class component, you have a choice between using the render props pattern or higher order components. The render props pattern can lead to messy code and a forced hierarchy if there are multiple instances. However, it is still the preferred way in cases where early returns are needed. When sharing component logic that doesn't require early returns, using higher order components can result in neater code. It's important to consider personal preference when choosing between the two patterns. Additionally, the example of the random image wrapper demonstrates the potential for creating reusable code by writing a generic fetch wrapper. However, it's essential to assess whether reimplementing existing solutions is necessary. Lastly, it is possible to wrap a functional component with a hook inside a class component to utilize the hook's functionality.
There's actually another interesting thing. If you write these things a lot, which you probably don't to be honest these days but there is one other consideration when people talk about these patterns, which is that like you can get naming clashes. And to be honest, that's unlikely, firstly, like be careful with your naming of your props but it's unlikely, but the way you generally do it is when you're defining your own custom one, it's like put yours first because if I do this, then now I might have a naming clash from, I don't know some third party library that implemented this pattern or whatever. So yeah, to be safe, but you are, be aware that also that isn't really solving the problem. That's just like, I'll be selfish and put the ones I want to be sure that they're gonna be there. So this was sort of always one of the criticisms, I guess, of this pattern. But anyway, that's a little bit of an aside. So that's the general idea. This is of course very similar to the example essentially. So what we do is then export this thing here as a main export on the file. And then if we come back across here and just have a quick look at the class component, higher order component. Yeah, we just import that function here. First thing you're gonna need to do, right, to get it to show... Remember it's a function that takes a component as an argument. So you need to pass it a component as an argument. Which component? This one, the one that we're in. Because this is where the component you want to get it on the props of. So that's where this sort of syntax comes in. And then yeah, that's now gonna show up on the props. So you can deconstruct these things from the props which is great. And then you can use them. And actually this is something I was discussing with a couple of you in the group as well is that for this particular case, you sort of have this choice right of like which pattern do you like better? So assuming that you have to use... You really need to reuse that component logic inside a class component. You've got a bit of a choice. And in some ways, this is kind of neater, isn't it? Because in the render, now you can sort of do if loading and if error here and it kind of cleans up our return a bit. Like this is a lot neater to read code wise. That's sort of one of the criticisms, I suppose, of the render props pattern is that it can sort of lead... It gets a bit like messy here. And imagine you've got a bunch of these. It can also lead to a sort of force hierarchy type situation if you've got... And then you've got like an additional one inside this return and it gets a bit hard to reason about, I suppose, but generally speaking, this is still the preferred sort of way of doing it. In this particular case where you've got loading an error, if you were sharing some component logic, that was just I don't know, maybe stateful, but it didn't have all of these sort of things going on where you needed the early returns, then yeah, a 100% I would sort of go for this. But yeah, it's curious to sort of reason, like just think to yourself, what do I prefer? And it's actually something as well that this random image, this wrapper that we've written is essentially like a reusable piece of code, right? But the direction it's going is essentially, you can imagine you could write your own generic sort of fetch wrapper here that you just use across projects and you just use a simple one. And I actually had that sort of use case exactly. And we just wrote like a simple generic one that we sort of used around the place. But you end up writing a library. So also after a certain point, you need to question like, am I re implementing something that someone else has done? Because there are fetch wrappers around already, but in this particular case, we're hitting a particular API and we want a particular thing, which is to reuse this bit of logic as well in conjunction with the return dates from the API. We want it randomized. It's not something that you get directly. So yeah, it could be a use case. Cool. I think that's probably it for the, for this for the most part, I think yeah. Any questions about anything that I just, just said before we just take a five minute break and then we'll continue.
I've got one small question. What is the reason why, if you have a hook that returns something, you can't use a functional component with that hook inside of a class component? Is there a reason for it? So are you asking why can you not use a, why can you not use hooks inside class components? Now, for example, I have a hook that I want to use for a part of a class. So for example, I make a function component with that hook and I use that function component inside of the class. Is that possible? Let me, so hold on, let me just share my screen quickly again, so if I understand the question, so where do you mean, like where would we do that? For example, if you have a hook that's creates a translation function that's returning the translation function, but I have a really old class components with, for example, a button that needs to be translated. Can you then wrap the button inside of a functional component that uses that hook? Yes. Yeah, absolutely. Yeah. You could do that. But the thing is, with this rule, the way to think about it is sort of like that example, I guess that we saw before back on this slide, is that if you're, if your use case is really simple, but where is it? I'm just looking for like this, on a base level, all you really need to do is like wrap. That's what like, if we just followed the error, like, that's what reacts asking us to sort of do is it's just like, you know, just wrap it. That's the thing. Yeah. So you can absolutely just do that.
17. Using Hooks and Functional Components
If a hook returns a value, it's a different case than when it doesn't return anything. In the latter case, you can pass data via props to a functional component that uses the hook. The hook must always be used inside a functional component. Refactoring a class component to a functional component is the first step. If that's not possible, wrap the component logic inside a functional component and use it within the class. When a hook returns a value, consider how to handle the return value, as you may need access to it.
Yeah. Okay. I was a bit confused because it was the case where you said if you use a return stuff from a hook, then it's might not be wise to use a functional component. Yeah. Yeah. I mean, if you, if it returns stuff, it's a different case to when it doesn't return stuff. That's the sort of the two different, the two different kinds of cases, I guess this is the slide I think I was looking for. Yeah. So like, you know, in this particular case, for example, what do you use documents? It doesn't really return anything. You see here it's like returning null. So if you just want to like run a side effect, it's very simple. You can just pass stuff in like via props so that you see it just needs to be, if you're going to use it in a class component. The thing is you need to be the hook needs to be used inside a functional component. That's just always the case. So that's sort of the logic to follow. But I would always, yeah. The way I would always reason about this is like, my first port of call is like, think about refactoring this class component to a functional component. If you can do that, then it's like problem solved, then just use the hook, like absolutely number one option. But then if you calm, then you start to say, oh, okay, well then what, what's the next? Well, yeah, then you can sort of say, I need to wrap that component logic inside a functional component and then use that functional component inside the class. And that will sort of let me do that. And then you just sort of build it up from there. If you have some return, then you need to think about sort of how to return things because you might need access to the return from the hook like here. Yeah. Hopefully that answers the question.
18. Introduction to Redux and Its Purpose
Redux solves the problem of state being stored in different components by introducing global state. It helps with the issue of prop drilling and allows for sharing data and having state available globally. Redux should be considered a refactor step rather than adding it upfront to a small application without the problem of state management. As the application grows, managing state in different components becomes challenging, and Redux provides a solution. It introduces a global state that can be accessed and updated by different components, avoiding the need for callbacks and simplifying the data flow. While simple examples may not require Redux, it becomes essential as the application scales.
Okay. Thank you. No worries. Cool. Any other questions before we just... I guess the plan now is just to do a quick sort of... Well, we'll just do five minutes because I think most people sort of finished the stuff with all of this. So we'll do five minutes and then we'll just like going to this bit and that'll give you enough time to do the exercise around context as well. But yeah. Any other pressing questions? Amazing. All right, cool. I will see you all in five minutes. Cool. Yeah, hopefully you all had a good break and are ready for the next part. I think, yes. Though I think a few people sort of joined halfway through this one, hopefully it all sort of made sense for those who did. I tried to sort of assign people to those different breakout rooms as we went along, but hopefully that washout made sense for those who sort of joined in the middle. And if you joined recently, then welcome. We're in the second part now, but the recording will be available afterwards. So feel free to go back and have a look at it as soon as it's emailed out, that will explain everything. And yeah, exercises let me know how you get on. Cool, I'm gonna start. Oh, it's got one more person. I am gonna start presenting the second part. So we should, I guess, in terms of timing, I guess it was sort of between three and four hours. So yeah, we'll probably, should be done presenting this bit in like 30 minutes and then the rest of the time we'll have for the exercise and I'll try and do a washup. So try and finish around 7.30, 7.45. But yeah, I guess we have until eight in terms of like absolute hard deadlines, but that's cool. Yeah, okay, I'm gonna just share my screen again quickly. Talk to you about context. Come for a break. Right, cool. So yeah, just moving on, I guess, to a slightly new topic. Which is like redux. We said, I guess, right at the start that we were gonna sort of have a little bit of a chat about this. I think it's relevant because, you know, when you work on a legacy code base that is definitely something that, yeah, that you need to sort of handle. So, sorry, I was just admitting one more person. It gives me all sorts of pinging noises and things. So let's recap quickly what's going on with redux. So I guess the question, question for all of you, if somebody wants to answer, is like, what is the main problem that redux is trying to solve? I'm kind of interested to hear what you think about that. But like, to be honest, I think you can nail it down to like one thing. But what is it? like what was the issue that redux solves for us when working with React? Less prop drilling? Data, yeah. Yeah, I agree, less prop drilling. Anything else? Sharing data. Sharing data, yeah, good. Global state, state that's available globally. Yeah, exactly. Yeah, I think these are all really good answers to getting there. Essentially, I guess the way that I would see it is really, it only really does one thing, which is this. The issue of state being stored in different components. That's what redux helps us with. And it does that by introducing global state, right? And this is something that I think is interesting just to point out, is often, yeah, often when we were doing workshops in companies like React.js Academy and also like boot camps and stuff, people would often say, when I say to them like, oh, start a React app. They'd be like, well, I'm gonna add redux up front, you know. Right away. I always say to people, like look, redux should be a sort of re-factor step because it's solving a particular problem. And you might not have that problem initially. Like, if your application is really small and you don't have a problem with state being stored in different components, then you don't have the problem, right? So because, you know, if we look at these images here, right, this is a tree of components. Like it's a tree structure and there's like a hierarchy. And the problem that you have is where essentially in React different components store bits of state, and it becomes very hard to reason about that over time as the application grows. Cause it's like, oh, who's responsible for what? Who's responsible for updating what? You have callbacks, which are passed down. Remember, there's the one way data flow. There's not, you know, state doesn't move back up this tree. It's just that you can pass down a callback and then that might trigger a state change in one component which would then trigger a re-render in all of his children, right? Which is what you can see with these arrows here. So it's like, this might've been passed down something and then, you know, this one now with this re-render is then all of the children will re-render. So, that's sort of how it works. And this becomes a problem of like scale. And always one of the challenges with like explaining Redux just generally and the issue that it solves is like, you don't have that problem when it's small. So it's really tough because if you want to like, sort of look at Redux as, I don't know, just from a standpoint of getting your head around it and teaching it, you want to use simple examples. But the simple examples mean you don't really need Redux. So it's a bit of a catch 22 on that one.
19. Redux: Centralized State Management
Redux is the idea of centralizing state management in one place, allowing components to subscribe to changes and dispatch actions to modify the global state. It has been successful in improving scalability and has been widely implemented. However, it's important to consider if it's necessary and to use it as a refactor step. React is a library, not a framework, so we have choices in how we manage state.
But anyway, it's something just worth thinking about. But that really is the sort of big idea with Redux is that it's like, instead of this thing of different components, managing these different bits of state, like, let's just take all of that and put it in one place like this one store. And then, you know, components can essentially subscribe to those changes if they want to. Like if they need to be notified about that, they can do that. And then also dispatch some stuff in order to go ahead and like, you know, change that bit of global state in a way that doesn't cause any mutations without sort of, you know, I don't wanna explain the whole thing of Redux, but essentially that's the idea, that's the big idea. And this was pretty powerful because it helped build like this is a scalability thing. And it's really good and React Redux, really like the library, which was the ByteInsurance, it sort of went a long way. And I'm sure many of you have seen that this has been implemented in code bases pretty extensively. And so yeah, it was pretty successful as a pattern. I guess I would say though that in some cases it probably went a bit too far and was implemented where it wasn't needed. So there's always worth thinking about these different things as a refactor step because in React, it's a library, you know, it's not a framework, it's got an ecosystem and we make choices about these things. So yeah, it's always worth considering.
20. Redux and React Redux Hooks
Redux works with React using the high-level component pattern. The connect function takes a component as an argument and returns another component. It breaks up the process into two functions: the first one takes some config arguments, and the second one is the higher order component that receives the component. The connect function grabs the state from the context and injects it into the component's props. If you already have Redux set up, consider using the React Redux hooks to refactor your components into functional components. This will tidy your code and eliminate unnecessary layers of abstraction. Context is used to provide access to global state at any layer of the component tree.
21. Using Context and Redux for Global State
The idea with context and React is you must explicitly ask for it. Before implementing anything context-wise, ask yourself if you need to broadcast a state change to multiple nested components. If not, try not to use it and just use Custom Hook. If you already have Redux as a global state solution, consider if the state needs to be in the global store. Refactoring to modern patterns allows you to implement your own global state. You can use the useReducer hook inside a context to recreate a mini Redux-style solution. Question whether everything needs to go in the store, especially with new patterns and options available. Some state may not need to be fully global, and there may be alternative ways to handle it. Consider these factors before deciding to use context or Redux.
But the idea is it's not fully global because as many of you probably thinking like, you know, global stuff is a bit sort of evil, gives you problems. The idea with context and React is you must explicitly ask for it. So you must say like, hey, is there this thing in the context? If yes, give it to me. It's not just there. It's not just gonna sort of show up on its own. But yeah, what you need to ask yourself before you even think about like implementing anything context-wise, it's just like, do we need to broadcast a state change to multiple nested components? This is sort of the big question. And the answer may very well be no to that question. Like, do you need, do they need to sort of know about this bit of state that's like changing all over the place? Possibly, but like possibly not. There are different sort of use cases for that. But I would really ask yourself that more than once because it's very easy to slip into this thing of oh, I'll just use the context API. And you might not actually have needed to do that if there wasn't something that changes and then you need to sort of pick up on that change in multiple places. If that's not your case, try not to use it. Just use Custom Hook on its own. It's normally more than enough. And yeah, if we already have like Redux which is a global state solution, the next question that we should sort of have for ourselves I guess is like, does this bit of state need to be in that global store? And so this is where when you're sort of refactoring to like modern patterns, you can implement your own like global state, right? If you say a piece of state needs to be global and you don't have any Redux, you can just do that and I'll show you that in a second. We basically like get some global counter state and that's a very sort of like simple, simple example but you can do that and inside that context, you can just use the use reducer and essentially recreate like a sort of mini Redux style no problem. So Redux, this job is sort of done there but what you can do if you've got a big application that's already using Redux is just start to question do I need this to be in the global store? Yes or no? Because there was a bit of, it can get a bit like dogmatic with Redux where it's like okay, everything goes in the store but the question has to ask at this stage especially with the new patterns that we have and the different options we have is does everything need to go in that store? Is that necessary in this particular case? And that's why I think it got a bit clunky, I'm just thinking of stuff like Redux forms for anyone that's used that. It's like oh, that's a bit much having every keystroke and everything going through there. So these are the bits of state where you think does it need to be fully global or is it just it's there another way of handling that? Anyway, a bit to think about here. So let's move on to just looking at a couple more code examples and then I'll show you the exercise for the context.
22. Creating Global State with Context
If you want to create a piece of global state with context, this is the way I would recommend going about doing it. There's more than one way of doing this, but this is a way that I found to be pretty neat.
So again, coming back to this connect, like we said, it was just to sort of grab some sort of state out of the context, essentially and then inject that via props. So yeah, like we can now do the same thing by hooks, basically. So if you want to create a piece of global state with context, this is the way I would recommend going about doing it. I'll just caveat this and just say there's more than one way of doing this, so there's no, you know. If you look at the React documentation with like how to use context, there's not, there's many different ways that you can do it. It's not like clear-cut, but this is a way that I found to be pretty neat. Hopefully you'll agree.
23. Creating Counter Context and Using Hooks
To create a counter context, set up a provider to manage the count and set count state. Use the counter context provider to pass the count and set count values to the children components. Alternatively, create a custom hook called use counter to access the context values. Implement the provider at the root level or higher in the component tree. Consider the performance implications of placing providers in the tree. Use the use counter hook in functional components to access the count and set count values. Refactor components into functional components and use hooks whenever possible. If using Redux, utilize the Redux hooks. Consider using contexts and hooks to expose global state if introducing new state that doesn't need to be in the current Redux store. Consider Apollo Client for state management with GraphQL APIs.
So first off, create your counter context like at the top, and then we need to create ourselves a provider, right? Cause we're trying to put something like on the context globally. And then we have a piece of state that we want to manage, like count, set count. So we just set it to zero for its initial state. And then yeah, the way that the API works is you do counter context provider and stick some stuff into that value prop. And what I'm going to put in there is the count and set count. And then I'm just going to say, okay, children, right? So any of the children who are around, again, that special prop for React composition model just rendered the children, whatever they are. They're not children as a function, but remember just children. So just assuming here that they're regular old components, like they're not like functions or anything like that. What you can do.
So one thing you could do then is like where you need, remember what I was saying before about you can just pull stuff off, you must ask for explicit. You could go to any component that needs this count and you could do the use context from React. And you'd need to also export this import it, you do use context, count context, then you can get access to these values. But there's probably a neater way of doing it, which is just create yourself a hook, which pulls the value of the context. Because this is what we were just like talking about before. Essentially, this was happening before they were just pulling stuff off the context that's what they were doing and then injecting it via props. We know from the exercise we just did that we can do that with hooks as well. So I would recommend taking this approach in the same file, define a custom hook called use counter. And all it does is do what you were doing the component what I was just talking about use context, count context. So you're in the same place and then just return it. That's it, that's all this hook does is just like returns whatever is on the context. So it's gonna be those two things. And that'll also give you the opportunity here to make a bit of a better sort of API for those people who are using it because if the context is undefined that means that they didn't bother to implement this provider. They didn't wrap like the app in this provider basically. That's what's going on. So in that case we could throw like a handy error and be like hey, use counter state must be used within a counter provider. And this is the kind of stuff you'd expect to see from libraries and as well. It's just like anyone that implements provider they'll give you an error like this. So yeah, why not do the same? Be nice. I mean, we don't have to. It's gonna work without that, right? But I think it's a good idea. So yeah, how does this look? You need to implement your provider at the root level or at least quite high in the tree. That's something yeah, that you need to think about. Sometimes you can just like wrap these up and put all of the providers in there. There's a small aside here that like with all of these providers, you might be thinking like, oh, it does all the matter. Well, kind of. I guess what I'd say is that the ones that change less often should be like lower down the tree, right? Because remember about this thing of triggering re-renders but this is sort of like a performance implication. This is very yeah, you'd have to be, you need to get quite in depth to get to that stage but essentially it's gonna work wherever you put the providers. But anyway, you can see I've got this Chakra Provider cause that's the component library using this app. But yeah, I just implemented my counter provider, I just ramped the app with that so now I'm getting some stuff in the context. And then we just need to simply use the hook in any component to get access to that. So I import my use counter from the counter context file and then inside like this functional component now I can just say like, hey, I want the count and I want to set count and they're gonna be returned from that use counter hook and that's it. And I think then the API for that is like super simple. So yeah, just before we like see some codes which we'll run through as well in the editor. Let's just talk about this quickly. You might be thinking, well like, it's a lot of options, what should I do? Yeah, that's happened, but I guess we're developers and we're like, you know, paid to make decisions so we do have some different options but the kind of way that I would suggest thinking about this is that if you can refactor a component into functional component use hooks, always do that. If you have Redux then first protocol use the Redux hooks like make that refactor and try to use the Redux hooks and sort of break it down. If you have React router then same thing, use their hooks. Like now most of these sort of libraries if you're working with a legacy code base most of the libraries which are causing this sort of wrapping effect with high road to components they have a hooks implementation like that's, you know so, you know, nine out of 10 times, we can sort of do that. What I would suggest when you're doing the refactors though is like try to identify first in the code base what are the easy targets? Like what's the low hanging fruit and go for those like, don't, you know go for like the chunkiest ones first that's gonna cause you some headaches and doing those will help you reason about the other ones. And you know, you can always implement some of the strategies that we looked at before as well. Now you know how, if you absolutely must keep using a class component in some cases like with any of these things, if you need to introduce a new piece of global state and you don't want to put it in Redux like, and you don't wanna go through that whole thing because you're sort of trying to maybe move away from that or you've reconsidered it, then yeah what I would recommend is consider using contexts and then using a hook to expose it. So like what we just saw. And this is kind of the direction of travel, I guess that most people go for like in most in greenfield applications today, I would be surprised if people went to Redux, people do, that's fine. Like it's a global state management solution. Like there's nothing wrong with doing that. But most of the time it's not what I see when someone does greenfield, it's like if they need some global state, they'll one pattern that's very popular is what I was talking about before. You just use the context as I was saying but you just have one essentially like a sort of global reducer using the use reducer, hook instead. And you just manage it all there. So just inside React cause you have the same tools inside React so we can just do that. That's something that's very popular to do. Obviously, if you're using a lot of your state management issues may be coming from stuff around dynamic data and API things. So if you're using GraphQL API, Apollo Client actually takes care of a lot of your state management issues. Again, they have their own hooks and they also implement like a cache, which also acts as sort of like a global store. And if you have that, I would definitely recommend reading up on like how Apollo Client free does, how to use their cache and the cache API because you already have essentially a Redux store right there. It's doing the exact same thing. It's like a sort of global storage, it's sitting in the middle. So yeah, there are lots of different things to think about here. It depends on your case, but what I would say is, yeah, have a think, think about how you want to refactor. And if you're going to get a piece of global state in your application that doesn't need to be in your current Redux store if that's your case, then yeah, go for this approach. And if you're doing a Greenfield application and you need global state, I would 100% start with this.
24. Using Context for Theming
That would be my recommendation. Let's see this in action and do the exercise. One good example where you would need to use context is theming. We wanted to manage the state of light mode and dark mode and expose a function on the context to toggle the theme. We put the function on the context in the theme context provider. In the themed app, we invoked the useTheme hook and passed the function to the onClick button. Error handling is improved by using the top-level provider pattern. When refactoring, try to question if a custom hook can handle the functionality. Use context for global state that needs to be accessed in multiple components. Be careful not to manage the same state in two places.
That would be my recommendation. I mean, as I say, it's kind of, there's lots of different ways to do it. Like, yeah, we could litigate this further, but I'll move on. So yeah, it's just sort of my recommendations I guess from my experience. But yeah, let's see this in action a little bit and we'll do the exercise as well. Just yeah, there's not many more slides.
So, what is this exercise with the context that you're gonna do? So it's basically down here. One really good kind of relevant example, I guess, of where you would definitely need to use context is when you have something like theming, right? Where you have like a light mode, light mode, and dark mode. Because you need to broadcast that to like a bunch of components, right? And they might be all over the place in the tree. It's a really good kind of example. I think even in React Docs actually, they talk about this as an example of like somewhere where you would need to do it.
So, let's have a quick look at this and then I'll let you all get in with your evenings or mornings or whatever time it is for you. Let's have a quick, let's have a quick look at how we might have gone about solving this. So everyone can see my screen again, hopefully, yes. So, yeah, what we wanted to get, if you got it working, probably something like this is the idea. Let's have a look at the code and how we might've done that. So if we have a look at the theme provider itself, we basically just needed to manage this piece of state. So this string dark or light, there were just sort of two, and then that's the piece of state that we wanted to basically toggle. So the only thing we really needed to do was just expose a function on the context, which allows for the toggling of this theme. This is how I chose to do it, some of yours look a bit different, but I mean, essentially what we do is just called our setter from the state there. If it's dark, flick it to light, otherwise it can flick to dark. So what we do then is say, okay, cool this function here, I'm just gonna put it on the context in this theme context dot provider. And then that's style provider, that's the one that sort of coming from style components and we're just like hooking into that. That thing takes whatever your theme is as a prop, but we've now sort, we wanted this like dynamic thing here. So all we're doing, I think this originally was something like this, right? So all we're doing now though is like, hey, instead of it being like, I want it to be whatever is here. And that means that when it's toggled, this will change, this will change, and then this will change. And then yeah, in terms of the hook, pulling it off exactly the same as the example, right? Like you just use your context, which was defined in the same file. We just defined it up there and line five at the top and then just return whatever's on it. And in this case, what is on the context for those who that hook is just reaching into the context and pulling it off is just this, right? But the reason that it's like in an object is you might start, I don't know, adding more things because you can add more things to your context. So I think it's always like, it's just, yeah, it's one of those things I really like to do is like sticking stuff in objects and then just deconstructing them on the other side because it makes it really, really extensible and things like that. So how do we do this on the other side, how do we consume it? So in themed app, pretty simple, really. Yeah, we know that that's there. So I just invoke use theme, that hook returns that function and I just need to deconstruct it and that's it. And then just pass it to the onClickButton, simple as that. And of course, the other thing that you have to remember with this is that you would have needed to have wrapped it because if you do not, then you will get this error. But that was kind of one of the things I guess if I do that. What's cool now is the error handling because this is just something quickly to point out that's why we did that. This is now like a better sort of developer experience isn't it, if I use this? Like use theme must be used within a theme provider. So if you've ever used any of these providers from other libraries, they're always gonna do that. It's like the same with the connect and the with wrap. Like all of these sort of things. They do this sort of thing where give you some good error handling for the hooks and it's like, yeah, you need a top level provider because with the hooks that ReactRoute uses, for example, you have the same pattern. It's like a top-level provider. Well, it's called router but it's a provider. And then you use the use location hook, for example, like inside a component, it's the same thing. And if you don't have the router, it'll flash you a very similar error. So all they've done, to be clear, is the same thing that we were doing just now which is the inside, the actual provider itself, they're gonna expose, you know, they're exposing in the library some hooks and those hooks are gonna have logic like this, which lets you know, like, hey, you've got to use it within the provider. So yeah, that's pretty much the solution to this one. Hopefully that sort of makes sense and you can sort of see, mm, still erroring. Not anymore. Hopefully that was fairly straightforward. A little bit more complex, I guess, than the last one. But again, I sort of, I guess the point that I would like draw home with this thing of like, context is like, you always wanna, always try to when you do refactors, like do stuff in stages, like try to question really, like can I get, is this something that I can just do with a custom hook? Like, if it's a side effect, like use local, like using local storage or whatever, or like the user, like you can absolutely just do that with a hook. If it's got a bit of state, the answer is like, maybe like the example I gave before, where like, maybe you have a modal that is one modal, right, in your whole application, then it's like, well then we can just use the custom hook and like manage that bit of state there. But if it's something like a theme where I need access to this, you know, in potentially multiple components because over here, you know, I need it, right, like, because this wrapper is pulling stuff from the theme, it's taking the background, the foreground from there, and maybe all over the place I need it, which tends to be the case with themes, then that's where you wanna sort of think, oh, the context. And same thing with the counter. If you need a global count and you say, oh, I need to know what that is in my header, and I also need to know where that is in some heavily nested component, like, you know, on the different page, whatever, then yeah, might be that you can put it in the context, but always like do it in those steps and sort of like be careful when you reach for context because you're introducing something global and it will, yeah, come with some complexities and be careful not to try to manage the same piece of state in two places. That will really be confusing, so.
25. Using Context and Global State
The solution to this is to do refactors in stages and question whether a custom hook can be used. If it's a side effect or a bit of state specific to one component, a custom hook can be used. However, if it's something like a theme or a global count, context can be considered. When using context, be cautious of introducing global state and avoid managing the same state in two places.
So all they've done, to be clear, is the same thing that we were doing just now which is the inside, the actual provider itself, they're gonna expose, you know, they're exposing in the library some hooks and those hooks are gonna have logic like this, which lets you know, like, hey, you've got to use it within the provider. So yeah, that's pretty much the solution to this one. Hopefully that sort of makes sense and you can sort of see, mm, still erroring. Not anymore. Hopefully that was fairly straightforward. A little bit more complex, I guess, than the last one. But again, I sort of, I guess the point that I would like draw home with this thing of like, context is like, you always wanna, always try to when you do refactors, like do stuff in stages, like try to question really, like can I get, is this something that I can just do with a custom hook? Like, if it's a side effect, like use local, like using local storage or whatever, or like the user, like you can absolutely just do that with a hook. If it's got a bit of state, the answer is like, maybe like the example I gave before, where like, maybe you have a modal that is one modal, right, in your whole application, then it's like, well then we can just use the custom hook and like manage that bit of state there. But if it's something like a theme where I need access to this, you know, in potentially multiple components because over here, you know, I need it, right, like, because this wrapper is pulling stuff from the theme, it's taking the background, the foreground from there, and maybe all over the place I need it, which tends to be the case with themes, then that's where you wanna sort of think, oh, the context. And same thing with the counter. If you need a global count and you say, oh, I need to know what that is in my header, and I also need to know where that is in some heavily nested component, like, you know, on the different page, whatever, then yeah, might be that you can put it in the context, but always like do it in those steps and sort of like be careful when you reach for context because you're introducing something global and it will, yeah, come with some complexities and be careful not to try to manage the same piece of state in two places. That will really be confusing, so. Cool, yeah. Any questions about-
26. Context Placement and Provider Hierarchy
I had an error in my code, but I couldn't figure out the cause. I asked for help in the chat and realized I missed adding a provider. We discussed the placement of the provider and the performance implications of unnecessary re-renders. It's important to consider which part of the app needs access to the context. We also explored ways to tidy up multiple providers and suggested using the useReducer hook for managing complex state. State management complexity can often be handled by external libraries like Apollo Client. It's crucial to determine when to reach for context and collocate state as much as possible. I shared a useful article on using context for further reading.
Yeah. I kind of had it working, and then I got an error. I put it in the chat, and I have the same code as you. Maybe it's in the app.js? In which one? App.js, this one? App.js, what line do you, or you have the functional component and the render component. You have the line 24. You have to have it a comment out line 24 and then run it. Should still work, I guess. Yeah. It should still work. Because that's these components that are in the example. So I should be able to just get rid of all of those, right? Because essentially, those are the example components, those are the ones that are showing up here. But it shouldn't, should be fine.
So that theme, that component, that's the top level one here, it's this one. And that's where you've got your toggle theme and your use theme. Oh, I probably didn't add that one to the.... Okay. I see, I didn't add, go to APPJSX one more time. So you could either, you've got to either add it there or right at the top level right here, what we talked about. Like, you've got to have that provider, otherwise that would flash the error we saw before. But another place you could add that, lower down in the tree, is actually in APPJSX, because you don't actually need it right up there. You could have it here, just depends where, which of the components that need access to that piece of context.
Okay, thank you. No worries, cool. Any other questions about this? Yes, I have a question, which is, if you were to have a rule of thumb as to how down the context could be placed within an app, what would you say? For example, imagine that instead of wanting, or instead of needing to style the entire app, you just wanted to style example one, for example. Would it be okay just to wrap one of the components with the context, or is it weird? Yeah, no, really good question, I think. I mean, so the thing is, with these providers, is they are often at the top level because of the nature of them being legal, but yeah, that is something you can kind of question. If here, you sort of, yeah, you go into app and you say, well, I only really care about it being on the context here, there's no reason why not to introduce it here, and actually there's a small... That's actually kind of a bit of a performance enhancement, because remember when components re-render, they'll re-render all their children as well? Now this isn't really a big implication until you're like really running something at scale, but it's just something to bear in mind, so generally speaking, even with providers like at the top level, the thing that's worth thinking about is like which thing is changing the most? So the outermost one is probably something like your roots, which is the racked router, because you don't tend to change that that much, and then it goes down from there. But yeah, you're absolutely right. When you're doing a custom, something that's a custom bit of context, you really can question that and move it further down the tree. That'll do two things, one it will clean this up, and second it will help out with unnecessary re-renders, because if something changes in here, it's gonna re-render all of the children, which is like this, but maybe it's also a bunch of other stuff, and you can look all of those and benchmark it and you'll see what I'm talking about. But yeah, really good question. I mean, I would consider doing that further down here. Another thing in the same vein that I was discussing with a couple of you in your little group is if you end up with a bunch of these, there's sort of different ways that you can tidy it. One of the things that you could do is sort of like create one more file which is called providers, and then you just put them all and then you just put children underneath and then you can just put in this top level like one. But the other sort of thing you can do is really think about yeah, if they're custom ones, do I need this many, could I do it in one? So if for example, encounter provider and then you end up with theme provider two and other providers for other bits of global state, you could start to say like hmm, couldn't I just like, is my application simple enough but like all of the state I need to keep track of, can't I just keep track of it in this one place? And then if that's your case, you would end up with a bunch of lines like six. So you might wanna like reach for the use-reduce-the-hook, manage that complex bit of state and just put that onto the context if that makes sense. That's another thing that I've kind of advocated for I guess because most of the time, you're not gonna have that much global state even in a Greenfield application because it's probably gonna be managed for you elsewhere. I saw a few of you looking at the, what's it called, the use-query. Like that's managing API stuff for you. If you have Apollo Client going on, that's also managing the API stuff for you. That's where a lot of state management complexity tends to creep in. So then it's sort of like what's left. Well, first question, can I do it on a hook. And if it's a side effect, you can. And then if you need something dynamic and I need to be able to set it and all that stuff, then yeah, you can reach for context, implement some custom context like we've been doing here. And hopefully you can keep it all quite neat. Yeah, hopefully all of that makes sense. What's the big guess? Cool. It's the tricky one, isn't it, because always when we're talking about, it's like a problem where these patterns are problems that you have as an app grows. They're not problems that you may initially have, and it's that thing of like, oh, when do I reach for this? And for example, with states, we already know, okay, try to collocate states as much as possible. So that's the rule of thumb. So maybe there would be something similar for the contexts. Yeah, exactly. I mean, all they're doing is, what we were talking about is there's a bit of state that's managed here. So if you say, what else is global state that I need to manage like here, and manage it here and put it like on this context, you know, there are sort of techniques you can do as well. There are other things to consider here as well, where it's like you might want to create more than one context, like one context for the set count and one for the count just so that you can create two hooks. And why would you do that? Well, you might not necessarily, where you use it, need both of these. You just need one, and it just makes the API a bit nicer. So there's some things like that as well that are worth considering. There's a really good article about this sort of approach to using context that Kelsey Doz wrote as well. I will post it, it's linked in the slides as well, but I will post it just now in the discord channel. I think it's this one actually. Yeah, this article's really good on this same topic. I was doing it a while ago, but you'll see it's sort of a similar idea to what we were looking at here. But yeah, I'll post it in our discord channel so you can read at leisure. Cool, thank you very much, Richard. Cool yeah, I think that probably wraps it up, but yeah. Can I show you my screen at the end? I couldn't get it to work and I have the same code. If it's okay with you? Yeah, yeah, sure.
27. Troubleshooting and Conclusion
If it's okay with you? Yeah, yeah, sure. This is the error I'm getting. And... Nothing was returned from render, use random image. The problem is on those files. It's somewhere else. I'm not sure which one, if I was to take a guess, it's probably somewhere in exercise two inside your render props component. Thank you so much. If there's no more questions, I will let everyone get on with their evening. Thank you very much for joining. Really good stuff, great work. I'll hopefully see you all in the next one. I'll be around during the rest of the conference, I'm gonna check out those things. So feel free to ping me on the Discord or reach out, I'm about, so yeah. You probably need to ask Clara or Daria to add you to the channels, I guess. Can you maybe post a link towards the document, the slides on the chat on Zoom? Yeah, I will. For me it says message failed to load. So we're not included in the channel, I guess.
If it's okay with you? Yeah, yeah, sure. Okay, for once, I'm missing something but okay. This is the error I'm getting. And... Nothing was returned from render, use random image. Okay, I see the code. Okay, and the code is, so this is the SIM provider. Yeah. That looks good. Yeah, this looks fine. It's the same as you basically. And then if I go to the STIM app, yeah, let's see in there, can I see any index.js as well? Looks okay. If you go back to the FEMA provider again? Yes. So that's the expo default user. Yeah, it looks okay to me. Haven't seen it yet. If anyone else sees it, I guess, I shout. It seems to be there's an error. Can I see the error again? Maybe it's coming from somewhere else. Yes, maybe the error is somewhere else. Nothing was returned from my error. Oh, but it's an error coming from use random image. Yes. Okay, well, I guess it's not anything to do with our theme stuff. So if you just go to app.jsx. I think it's coming from somewhere else though, basically. If you comment outline 25 as well. And then comment outline 30 and line 34. Yeah, okay, now I should now save it. It should work. Yeah. Okay, so the problem is on those files. It's somewhere else. I'm not sure which one, if I was to take a guess, it's probably somewhere in exercise two inside your render props component because I saw the name of it was with the capital U. But I mean, yeah, it's gonna be in one of those rather than this one. Okay, thank you. I'm sorry about that. Thank you so much. Cool, I guess. Yeah, if there's no more questions, I will let everyone get on with their evening. Thank you very much for joining. Really good stuff, great work. Yeah, please feel free to star the repo, fill out the feedback form. Say nice things if you liked it. I'll hopefully see you all in the next one. I'll be around during the rest of the conference, I'm gonna check out those things. So feel free to ping me on the Discord or reach out, I'm about, so yeah. Cool. Will do, will do. For the rest of the people they're seeing the channel in Discord, right? Because I don't have it in my channel. You probably need to ask Clara or Daria to add you to the channels, I guess. Yeah. It's a channel called hashtag April7-modern-react-patterns. Yeah, but I mean, I am included in some of the channels but not in that one, some of the workshops. Yeah, me too. Yeah, me too. I mean, next developer job, it's probably a different seminar that took place at the same time. But we got mixed up, so we're not seeing... Can you maybe post a link towards the document, the slides on the chat on Zoom? Because by the time we'll get added, we might miss it. Yeah, I will. Let me just, if I can, I'll just put... Maybe you can find your way there with this link as well. Let's see, following it. No. Okay, I mean... For me it says message failed to load. So for me it was, I could not load the messages. Please try again. Yeah. So we're not included in the channel, I guess.
28. Troubleshooting and Conclusion
Let me see if I can. Even if you try to try again. Try again. Try again, it doesn't make any sense. It's okay. Because it's locked and we are not. Yeah, We're not... Yeah, no worries. I'll just, hold on, this link should work for a link to the slides. Okay, cool, thanks. Yeah, it's Google Docs, so, no problem. Thank you. So I guess that now you get an email from us, for access. Hold on, let me... The 20 of us. Yeah, I mean, it'll be all posted on the... I'll hit, hold on, anyone with this link can view, here we go, hold on, let me get another link. Or maybe Richard, I don't know if the organization is going to send us another email with the recording and also the slides and all the Github info and all that stuff maybe? Yeah, it's all in the Discord. The thing is with Discord is that unlike this chat here, it's recorded, so that's why if you can get access to the Discord channel, it's just persisted essentially. But I think when this call ends, we'll lose this chat. So that second link, though, that I just pinged you, should that work? I was just fiddling with the...
Let me see if I can. Even if you try to try again. Try again. Try again, it doesn't make any sense. It's okay. Because it's locked and we are not. Yeah, We're not... Yeah, no worries.
I'll just, hold on, this link should work for a link to the slides. Okay, cool, thanks. Yeah, it's Google Docs, so, no problem. Thank you. So I guess that now you get an email from us, for access. Hold on, let me... The 20 of us.
Yeah, I mean, it'll be all posted on the... I'll hit, hold on, anyone with this link can view, here we go, hold on, let me get another link. Or maybe Richard, I don't know if the organization is going to send us another email with the recording and also the slides and all the Github info and all that stuff maybe? Yeah, it's all in the Discord. The thing is with Discord is that unlike this chat here, it's recorded, so that's why if you can get access to the Discord channel, it's just persisted essentially. But I think when this call ends, we'll lose this chat. So that second link, though, that I just pinged you, should that work? I was just fiddling with the...
Okay, so I think I posted in the troubleshooting channel and Daria Xavala is telling me to direct message her my order number. So I think that they are missing ordering people and... But yeah, but anyway, that link that's in our chat right now that now definitely is working because I've opened it up to anyone with the link. So for those who is here, yeah, you should be able to see that and then I will now post that in the Discord channel, too. So... Thank you, Richard. No worries. Thanks a lot. Yeah, thanks. Cheers. You too. Have a nice day. Cool. Thanks, everyone. Bye. Bye. Thank you. Thanks. Cheers. Thank you so much.