From the course: Learning Full-Stack JavaScript Development: MongoDB, Node, and React
Invoking component actions in children
From the course: Learning Full-Stack JavaScript Development: MongoDB, Node, and React
Invoking component actions in children
- [Narrator] In the previous chapter, we started writing API endpoints to work with data in MongoDB. The last one was this endpoint to fetch information for a single contest. We're going to use that next. Let's make the application navigate to a single contest view when we click on a contest in this list. First we'll need to define a click handler. That's in the contest list. That is actually in the contest preview component. We'll do the click handler here. We can define it on this surrounding div. So clicking the name or the category will take us to the single contest page. So we can do onclick here, dynamic expression. And let's come up with a function here, name it handle click. Handle click is a function that we need to define in this component. So we define handle click as a function. And this function receives the DOM event, the native object that the browsers prepare for every interaction. And for example, we can do calls on this DOM event. One call we usually do here is to prevent any default operations on the event. Usually this is needed for anchor elements, but it's a good practice to always prevent the default DOM behavior because we're doing this operation through React. So what do we need to do here? Well, we need to navigate to a new view, and we need to use a state element to make React rerender the app and render a new view. The component that renders the contest list is the app component. So we actually need the state to be here in the app component. And here's how we can do that. Let's design the app to have a page variable. And that page variable can be either contest list or contest. So, we put this page variable on a state element. So let me name this element page. And the updated function is set page. This is a React use state call, and it starts by default with a contest list page. We need use state from React, import use state from React. And now we can add a conditional here that only renders the contest list if the page is contest list. And if the page is contest, it will render a single contest view. Let's create a function here, and I'll name this one page content. And this could be a simple switch statement. We only have two pages, but let's plan for growth here. So a switch statement is going to switch over page, the value for the page. And when the value is contest list, it will return this thing here. We don't need breaks here because it's the only statement that's going to be here in the page content function. So we can just return contest list. And similarly, if the page is contest, then we'll need to return something else. For now, I'm just going to return a text, and we can use this here as a dynamic expression. We just call page content as a function. Since it returns a value, that value can be used. So page content switches over page. If it's contents list it will render this contest list component, otherwise it will render three dots. So really what we need in that click handler that we just defined in the contest preview is to set page to contest. So let's do that. We'll do it the simple way first, and then I'll show you a better way. Our component tree, if we look at the components tab, app renders contest list, it renders contest preview. The page state is right here on the app component. We can actually test our state here by changing this to contest immediately. And take a look, it changed the view to render the new content that we're about to prepare. No contest previews were rendered. However, since the state is in the app component and we need to invoke it in a contest preview component, we'll have to pass it down the tree to contest preview, which is not ideal, but let's go through this exercise. So let's create a new function here, name it navigate to contest. And this function will simply set the page to be contest. That's our first part to navigate to contest. And this is the function that I need to call in the contest preview component. That means I need to pass it down the tree. So contest list will receive it. We can name the function here on contest click. And on contest click, what we're interested to do is to navigate to contest. I'd like to define the functions before we use them. So let me move this function before page content. And TypeScript is complaining because we have a new property in contest list. So let's go use it. So we have initial contests and we have a function, what to do on contest click. And we need to pass it again,, down to the contest preview components. So in here we can name it onclick 'cause it's a single contest component. And onclick, we're going to pass in the on contest click. And in the contest preview component, we now have another function onclick. So we can define it here. And since we have a TypeScript definition for this one, we would need to include it here as well. And I'll just use any here, again, to have our focus on the task in hand. So now that I have an onclick function that was passed down from app to list to preview. And all I need to do here is call it. This is the function, so we just call it. And I think we can test that. So we go in here, looks like I need to restart this thing, and we can test now contest list. And when we click on a contest, we go to that new view by changing the state. So what we did here is we made a child component change the state of a parent component two levels up in this case, by using this technique of passing down props to children. This is the simplest thing we can do in React to have a state shared between multiple components, and give these components the power to change that state. But it's not ideal. We're adding a responsibility here for the contest list that's basically unnecessary. The concern of what to do in a contest should be in the contest preview component. The contest list should not bother with that. This problem is known in React as props drilling. We had to pass a prop multiple levels down the tree to be able to use this shared state. An alternative solution to props drilling is with the use of React context, which gives us the ability to create a global state and give any component in the tree access to that state directly without needing to do props drilling. This however, is a bit of an advanced area in React. So I'm going to keep the simple method here of passing down the props to the component that needs them. And after finishing this course, it will be a good exercise to go through React's context and try to avoid props drilling in the code base.
Contents
-
-
-
-
-
-
Invoking component actions in children7m 40s
-
(Locked)
Displaying a different root component4m 7s
-
(Locked)
Fetching data after navigating to a new view7m 15s
-
(Locked)
Handling browser navigation history7m 14s
-
(Locked)
Server-side rendering of a custom path7m 28s
-
(Locked)
Fetching data conditionally4m 16s
-
(Locked)
Navigating on link click6m 11s
-
-