‫Let's now implement the first feature of our app
‫which is the ability to add new friends to the list.
‫So let's come here to the FormAddFriend component
‫which is where that is going to happen.
‫So the first thing is that we need to get the value
‫of these input fields into our application.
‫So right here into this component.
‫And how do we do that?
‫Well, as we already know, we use controlled elements
‫where we will have one piece of state for each of the inputs
‫and then as the user types something here,
‫that value here of the input field
‫will be synced with that state.
‫So let's do that,
‫and let's write name and setName.
‫That then, as always, we call our useState.
‫And let's immediately do the same thing also for the image.
‫And now all we have to do is to wire up
‫these states to our input fields.
‫And we have done this many times at this point,
‫so this is hopefully nothing new for you.
‫So again, we first define the state,
‫then we set the value to that state.
‫So basically controlling that input field.
‫And then we listen to the change event
‫with the onChange listener.
‫And what we do is to take the event,
‫and then update the state
‫using that event.target.value.
‫Alright, and let's see.
‫That should already be working.
‫Let's come here to the, well, so to the form itself.
‫And then we should see the state down there.
‫Well, somehow that doesn't really work.
‫Let's try that again.
‫And, well.
‫Yeah, here it is, so that's the state,
‫simply my name written wrong. (chuckles)
‫But yeah, let's not do the same thing here
‫in this other input field.
‫So value, image, and then onChange,
‫e setImage to e.target.value.
‫All right, then we get some error here for some reason.
‫So let's just reload,
‫get some more space here.
‫And then we should, of course,
‫see this state already in the component.
‫And there it is. Nice.
‫Now actually here I want some default already.
‫So let me show you what exactly that is.
‫So by default, we already want this part here
‫of the image URL.
‫So let's copy that, and then let's come down here.
‫And so by default, this will be our image.
‫And then when we actually create the new friend,
‫we will add something to it in order to make it unique.
‫But anyway, now the next step is here to listen
‫for the onSubmit event.
‫So again, just like we have been doing before.
‫So this submit event will get fired
‫whenever we submit a form by clicking,
‫so there on that button or hitting Enter
‫while we are in one of these fields.
‫And so then that submit event gets fired off,
‫and then we call the function, which will be handleSubmit.
‫So then let's create that function, handleSubmit.
‫And remember that this function here gets called
‫by React with the event object.
‫And so then the first thing that we have to do
‫is to prevent the default action
‫which would be to reload the entire page,
‫which is not what we want in a single-page application
‫like we are building.
‫And so the event handler function for a form,
‫so on an onSubmit, always needs the event.preventDefault.
‫And now let's create a new friend object
‫so that we can then add that to our array.
‫So that should have name, image,
‫and the balance should start at zero, of course.
‫So no one owes anyone anything.
‫We also want an ID.
‫And let's create the ID using the built-in browser
‫crypto.randomUUID.
‫And so this is a very good way of generating
‫random IDs right in the browser.
‫So this is not an external packages,
‫but it won't work in older browsers.
‫But here we don't care about that.
‫We just want to make this work.
‫And so with this, we have a new friend.
‫Let's log it to the console here for now
‫just to see that everything is working correctly.
‫Give it a safe. Let's reload here.
‫And now in the console we should see that object.
‫And indeed, there it is.
‫So balance, and here I didn't call the function.
‫I just passed in the function,
‫which of course is not correct.
‫Let's try that again.
‫And now here it is.
‫So this is the random ID that was generated.
‫Here is the image and the name and the balance.
‫Now as I was saying,
‫I actually want to now add something to this image,
‫so to this string that we already have as a default.
‫So let's create a template literal here.
‫And to now I want to do equal and then the id.
‫Well, now of course we cannot do that.
‫So let's create this here outside as another variable.
‫So const id equals this,
‫and then down here just like this.
‫So the way that this works, and the reason
‫why we are adding this id here is that this string here,
‫this URL, if we open it,
‫it will basically give us a small image with the size of 48.
‫But when we reload,
‫it'll each time give us a different image.
‫But of course we don't want that.
‫So we want each image to be fixed basically to the person.
‫And the way we can do that is to attach something here.
‫So it doesn't matter what string,
‫but now each time that we open this URL,
‫we will always get the exact same image.
‫So it'll always be this one here.
‫And as I reload, we should get exactly the same.
‫Well, that didn't work actually,
‫but maybe that's just because someone else
‫has already used this.
‫But yeah, this here should be pretty unique.
‫And then we should always get the same image.
‫Now there's just some small changes that we should do here.
‫Ah, of course not here, but here.
‫So first, after we submit the form,
‫then we should go back here to the defaults.
‫So let's do that.
‫So set the name back to empty
‫and set the image back to,
‫well, to just this here.
‫Because, of course, the user could want to input
‫some other URL here, it doesn't have to be this one.
‫It's just the default that we're using
‫so that we don't have to write this manually each time.
‫So if we try this again, then you see that it gets empty.
‫And here, it should then also go back to the default.
‫Now if we submit this right now without anything,
‫then, of course, something will still get locked
‫to the console.
‫So all of this here, all this code is still executed.
‫But we actually don't want that.
‫So let's add some guard clause here
‫saying that if we have no name or we have no image,
‫then return immediately.
‫And so in this case, nothing is going to happen.
‫So with this, nothing happens.
‫But if we have a name, then of course the code works.
‫Okay, so the form now works, but now comes the harder part.
‫So how do we now actually get this object
‫that we locked here onto our FriendsList?
‫Well, let's think about it.
‫So each time that we add a new friend,
‫we want that friend immediately added here to the list,
‫so to that UI right here.
‫So we want something to happen in the UI,
‫or in other words, we want the UI to render.
‫And so once again, that's a clear sign
‫that we need some state.
‫So that is pretty clear, but now we need to figure out
‫where to place that piece of state.
‫And for that, let's take a look
‫at our component tree here once again.
‫Yeah, let's see all of it.
‫So our FriendsList component here is the one
‫that is going to display the friends, right?
‫However it is the FormAddFriend where we want to update
‫that list of friends because, well, of course,
‫this is where we add a new friend.
‫So the update happens here,
‫but the state itself is needed here
‫in this sibling component.
‫So what does that sound like?
‫Well, it sounds as though we have to lift
‫the Friends state App here into the App, right?
‫Because this way both of these components,
‫or actually all of them can get access
‫to that Friends state.
‫So let's do that.
‫And first of all, let's go to the FriendsList itself
‫where right now we have this friends here
‫set to initialFriends.
‫And so now let's get rid of this part.
‫And instead let's create a lifted up state variable
‫in the parent component, which is, in this case, just App.
‫So friends and setFriends
‫and then useState.
‫And what should the initial value be now?
‫Well not just an empty array
‫because we actually want these three friends here
‫to be visible at the very beginning.
‫I mean, it probably doesn't make a lot of sense
‫for all the users to have these three friends,
‫but let's just say that this is how it works.
‫So let's just say that these friends
‫are basically the default friends of everyone.
‫Because this is just a demo anyway.
‫Now here then of course immediately get the problem
‫that inside the FriendsList, friends is no longer defined.
‫So we need to fix that by now passing in friends as a prop.
‫So giving this component access to the state
‫by passing it down as a prop.
‫And so here we receive that,
‫and then the component will be happy.
‫So it's back to having this array,
‫and then everything works again.
‫Great. So that's one part.
‫And now we need to give this form here
‫the ability to add new friends,
‫so to update that friends array.
‫And we could do that in two ways.
‫So we could directly pass the setFriends function
‫into the, where is it?
‫Yeah, here. So right here into this form.
‫But let's keep all the event handler functions right here.
‫And so let's instead create a function
‫called handleAddFriend.
‫And then this function here will use
‫that setFriends function.
‫And then we pass this one here down instead.
‫Okay, so let's use setFriends.
‫And of course this function here then needs to receive
‫a friend object, so that's the new friend
‫that we created down there in that component.
‫And then here, all we do is to take the current friends,
‫which again could be called anything here
‫in this new function, and then we create a brand new array,
‫spread the current friends in there,
‫and at the new one at the end.
‫So again, we do it like this,
‫basically creating a brand new array
‫instead of using like the push function
‫because that would mutate the original array.
‫So it wouldn't create a new one,
‫and so React in that case would not re-render.
‫I mean sometimes it might actually work,
‫but it's not supposed to, because in many situations,
‫it will actually not work.
‫So don't do that, don't mutate original arrays
‫because React is all about immutability.
‫That's also the reason why we are not allowed
‫to mutate props, remember that?
‫So always creating new arrays here.
‫And the way we do that for adding a new element
‫to an array is by creating a brand new one like this,
‫spreading all the current elements
‫and then adding the new one to the end like this,
‫so just like we have been doing.
‫And now let's pass that in here.
‫So onAddFriend like this,
‫we pass in handleAddFriend.
‫So again, we are using this on prefix here
‫just like React does it for the events
‫like onClick, onChange onMouseOver.
‫And so here we create our owns basically like onAddFriend,
‫so as if this was also an event.
‫Okay, let's copy this.
‫So this should already be working now.
‫And so then let's come down here,
‫pass that in.
‫And instead of logging it to the console,
‫we now want to call this function with the newFriend.
‫And this should now work actually.
‫So we have wired up everything correctly.
‫So we have our shared state here.
‫So our lifted App state
‫which is now available to the FriendsList.
‫And we then update that state down here in this component.
‫Well, not this one, but...
‫Ah, it's not in the tree, of course.
‫Now it will be in the tree.
‫So this was actually a good learning moment.
‫So basically seeing that the component
‫that was not in the UI is of course
‫also not in the component tree here, right?
‫So now it is, but when I close it,
‫you see that it disappears from here.
‫Okay, but now it is back, and so again,
‫this is where we will update the friends state
‫and in a way do some child-to-parent communication.
‫So the parent being the App component.
‫And so then as soon as that state is updated,
‫it's again passed down into the list
‫which will then re-render.
‫So let's try. And there it is.
‫You and Jonas are even.
‫So this should now create some image there.
‫It always takes some time for some reason.
‫But yeah, that worked beautifully.
‫And we can keep adding more and more.
‫And then this updates the state exactly in the way
‫that I have explained before.
‫Here we update then that propagates the update
‫basically to the App component, which will then pass it
‫down in the list, which will re-render as a result.
‫Nice, there's just one small thing that we want to do,
‫which is each time that we add a new friend,
‫so that this form is submitted,
‫we then want to immediately close that form,
‫so make it disappear again.
‫So that's easy enough.
‫But let's think about it a little bit.
‫So do you think that we should do that here?
‫So in this component here,
‫is this where we should close the form after we're done?
‫Well, not really, because this part here,
‫this form is actually not responsible
‫for showing itself or not.
‫So as long as this component is actually included
‫in a component tree, it will be visible, right?
‫So instead, who controls whether this component
‫is visible or not is the App component by using this state.
‫Right, and so we can use this handler function
‫to not only set the new friend state
‫but also to hide the form again.
‫So all we have to do is setShowAddFriend
‫and set that to false.
‫So here the state doesn't depend on the previous state.
‫So here we simply want to always set it to false.
‫And yeah, we got the new friend, and the form is hidden.
‫And so this actually completes this feature.
‫So just make sure that you take now a minute
‫to review the code that we wrote here,
‫so in particular the lifting App state,
‫and how we then wired everything together.
‫And then once they're done, we will start working
‫on actually making this main part
‫of the application work as well.