The course is part of this learning path
This module looks at how to manage state in React. You’ll be looking at state management, context, and reducers.
The objectives of this module are to provide you with an understanding of:
- State Management
- How to create and provide context
- How to provide dispatch
This learning path is aimed at all who wish to learn how to use the ReactJS framework.
We welcome all feedback and suggestions - please contact us at firstname.lastname@example.org to let us know what you think.
- [Instructor] We're now going to look at how we can consume context and components. To consume the context we need to create our own hook. This will be done in the same place that we created the context. The purpose of it will be to return the context value that's created when we actually use context hook returns it. It needs to be done here so we can have access to the context and the provider. We'll give our hook its own name. Usually use followed by the context name. As you can see, a hook is essentially a function that returns something. We actually use context hook accepts a context object and returns the value for the current context. It gets the value from the provider. We then return this context value from our hook and export the hook for use in any component. Any child of a provider component can use the context. The value is provided with is decided by the value prop of the nearest context provider above the calling component in the tree. If the provider updates, the useContext hook will trigger a re-render of the component tree that consumes the value. We've now updated the courses provider to have a useCourse as context hook. This sets context to be the result of calling the useContext hook with the courses context. Just to be sure that it's used correctly, we check to see if context is undefined. If it is, it means that it was no provider for the component trying to consume the context. If this happens, we throw an error. The function returns the context, which is essentially the value defined in the provider component, and in our case, that's an object with a key of course, and an array of course objects as its value. The function is exported for use in any component at once to access this context. Remember, we should get an error if we forget to provide the course context further up the tree. We deconstruct the object returned by context to get the courses array. That's on line 16. Getting the value here means that we've been able to remove the need for a course is stating the component. Don't forget that if the value in the context of dates, the provider will re-render and as the filterable courses table is a child at that provider, it will re-render with the new value. You should also notice that all of the logic to make network calls for the courses data has been removed from this component. We'll use some of that logic when we deal with making the call in state management code later. The components still has the internal state we decided on way back in part three and four, thinking in react. The search text and the advanced values are only related to this part of the app. So no need for any context here. To deal with errors in the courses array, we just slightly modified the way in which this is done. We'll make the courses array contain a single element, that is an object that contains a status key and a message. We can do that when we handle the data coming in. So we have no dependency on any other system for that. We've declared our error array to render an error component on line 18. And we populate this in the if statement on line 20, checking to see if the first element in the course array is an object with a key of status. We then push the relevant components to the error array dependent on its value and render it when needed. There's a little change in the conditional rendering too. We're showing the new code on the left and the old code on the right to help you compare it. We've replaced the errors and errors on line 74 of the older version of the filterable courses table code with a check on line 49 on the new code to see if the errors array has a length greater than zero. This ensures that the error component will render if there is one. The ugly array.isarray expression on line 75 of the old code is removed and replaced on line 50 of the new code with a check for courses array to have length and the errors array not to have a length, in order to render the courses table. To render the loading message line 57 on the new code, we checked to see if errors and courses array have no length. And we've added to check to the rendering of the route to display a course in the newer component to remove a warning we will get if no courses were present in the context. If you're wondering why there's such a big difference in the number of lines, 23 to be exact, it's because the new version of our component uses context. That means we can remove all of the code that deals with make an asynchronous calls for the data, the get courses function, and the use effect to ensure to re-render when the course is updated. We've also removed two states from the component, courses and arrays, and replaced them with the variables that get their values because of the context. You can see where code has been removed and replaced here. Our new component now only takes data and displays it using some conditionals to ensure the correct view. The removal of the asynchronous logic makes this component more reusable. We could make it more generic just to create a filterable table of any data with minimal changes to suit different data. We've been able to do this through context, although we could have done this for the example, just by lifting state to the app component. However, this abstract example is a powerful demonstration of the potential for context in large complex apps.
Ed is an Outstanding Trainer in Software Development, with a passion for technology and its uses and holding more than 10 years’ experience.
Ed is responsible for delivering QA’s Programming Foundations course using the Eclipse IDE. His skillset extends into the DevOps sphere, where he is able to deliver courses based around Agile/Scrum practices, version control, and CI/CD.