When dealing with Components, there’s often the need to either have some local state controlled by the component (such as form input fields) or to tap into the lifecycle events of the component. In this lesson we’ll give some practical examples of both.
[00:00] Here we have a component that renders a <div> onto the screen, and inside it, it places this user card. The user component receives both the image and the name through props.
[00:11] Now let's say we want to retrieve this data from an API instead of hard coding it like this, and we want all of that to be managed by this app component. To do that, we'll need to convert this into what is known as a stateful component.
[00:23] Right now it's just a function, but we're going to use ES6 classes instead, so the first thing we need to do is bring in component from preact. Then we can change this from being a function to being a class, and we'll extend component.
[00:41] Components have a render method, so we can keep this code here. We just need to wrap it in that method. If we just say render, move out there, and this actually will still function exactly as it did before, as you can see.
[00:58] The main difference, though, is that we can now hook into this component's life cycle events, such as when it mounts to the DOM and when it unmounts, and we can also use it to store some internal state. As we're going to fetch this user data from an API, let's set some initial state on this component. We can do so inside the constructor.
[01:20] This receives some props. We call super with props, and then we can go ahead and add the state that this component will be in before the Ajax request has even happened. We can save this.state, and we can set the user to no, and loading to true.
[01:39] This will allow us to show a loading indicator whilst the Ajax request is happening. The whole point of having this internal state is that we can access it inside the render function, so let's first handle this initial loading state before any Ajax has happened.
[01:52] We can check the value of this.state.loading, and if we are in a loading state, we'll just return please wait. If we're no longer loading anything, then we can just return the user component. As you can see, we are always in a loading state now because we set this to true here, and we're not doing anything to set it back to false.
[02:18] The next step is to actually fetch the data from the API. To do that at the correct time, we can hook into this component's life cycle events, in particular, componentDidMount. We'll add that method to our class, and preact will call this method whenever it has actually inserted this element into the page, so it's a safe time to begin our Ajax request.
[02:40] We'll use Fetch, and we'll provide a URL for GitHub's API. If that's successful, we'll convert the output to JSON, and if that completes without error, we should have our user object. We can log this to the console just to confirm everything's working correctly.
[03:07] Back to our page, and you can see here we have this data from GitHub's API. To use this data within our component, we'll need to set the data on the user and set loading to false. We'll call this set state, and because we're not really relying on any previous state, we're safe to just provide an object here.
[03:30] We can say user and loading false. We save that, check the browser. We can see that after just a moment, we now get this user card being displayed. Whilst we're here, we'll just add a log for any errors that come out, and now we can update our usage of the user component to use real data from the API.
[03:57] For name, we'll change this to this.state.user.name, and for the image, we'll use this.state.user.avatarURL. Now, you can see that when we reload this page, we get please wait for a moment, and then we get our user card being rendered with real data.
[04:23] Stateful components also have props, just like functional components, so we use this.state to access properties that are updated by this component. If a parent component wants to pass anything in to us, then we can access it through props.
[04:38] To give us all an example, let's say we didn't want to hard code this URL here. We could extract this, and instead retrieve it from this.props.urls.user, and we could set this at the point in which we use this component.
[04:58] For us, it's in the index file here, so let's create a configuration object. Say const config = an object, and then we'll say we have some URLs, and the user URL will be that GitHub API. Then we can pass in that configuration under the config key.
[05:26] Now, back in our app component, we can see that I'm trying to access props.urls, when actually we said it was named config. We save that and reload. You can see it's working again. Often, what you'll see is stateful components using both props and their own internal state.
[05:47] The key takeaway from this lesson is the difference between these stateful components and regular functional components. Stateful components handle things like Ajax, and time, and their own internal state and life cycle events when they're put into the DOM and removed from the DOM, for example.
[06:05] Whereas functional components like this user one here, they just accept some properties and give back some elements, nothing else.