Guide to Using Functional Components in React
Welcome back to the react course where we are building out the Bottega Mad Lib app and in the last guide we added a whole bunch of styles to our mad lib form component and we also styled our inputs and in this guide we will be introducing functional components and we will be using one to render out our inputs from now on.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

All right so to get started go ahead and head over to the link in the guide. It's react. So in here the first thing we have is a functional component it says the simplest way to define a component is to write a Javascript function so if you copy that and you head back to your application and let's start by closing everything by clearing our console and opening up our madlib_form.jsand above our class paste in the welcome component and make sure it's out of this class and let's just use this so I can show you what's going on here.

medium

So the way we use this is the same way we use any other component like row, column, card. So <Welcome/> and then we close it off if we go back to our app and reload the page you'll notice that it says "Hello" but that's all it says. So we looked at props in a couple of videos before this and we're going to add a prop in now. So in welcome, we're just going to pass in Max and we're going to copy this a couple times and put in some other unique values so Andrew or Jordan and then we can save that reload the page and you'll see that it says "Hello, Max", "Hello, Andrew", and "Hello, Jordan". So basically a component's awesome because we only have to write code once and then we can just call it much like a class in object oriented programming and much like this very component we have right here. For example, if I went to our app.js and I copied my mad lib form three times and then waited for the changes we'll see where we get look. It's our component three times. So wouldn't it be really efficient if we wrote this input component once and then rendered it out four times. Yeah, I'd be a lot more efficient so let's get rid of those mad lib form component instances and these welcome instances and what we want to do is actually take one of these inputs copying it and throw it in here. Make sure we put parentheses there and then just put it in there now let's rename this to MadlibInput and then let's indent this back a little bit using shift tab once we select the entire set of jsx.

large

All right now let's save this and let's also make a call to it. So <MadlibInput /> and reload the page and you'll notice it won't work we will get an error, so go into the console and you'll notice it doesn't load at all.

large

There should be an error. So we're getting cannot read property of handle change undefined.

large

The reason we're getting this is that we have this function in here saying this.handleChange but if you understand what this is then you'll understand why this doesn't work. This is referring to the instance of this component. So right now this is referring to MadlibInputand model of input does not have any function called handle change mad lib form does though. So the way we can fix this is by taking our entire function and passing it in as a prop that way were still referring to this handle change before it gets into this component. So go ahead and just copy this cut it out actually

large

and let's just type in props.handleChange and then we can go down to our call and we can put

large

So now when we do this when we save it and we wait for it to reload we'll notice that it works. Okay so let's go ahead and put this in a row and let's actually replace that with the color we have right here.

large

Save that wait for it to reload or just hit command r and you'll notice it looks exactly like it does before and it does the same exact thing. So that's great and all but let's do it for the rest of our components here on screen. We have a plural noun, adjective, and we have a celebrity. So the first thing you might think about is okay this is color and this is color. So how can we change that we don't want the rest to say color. So what we have to do is pass more props. So instead of passing in all of these props in here what we need to do is think of a more efficient way to do this and a great way to do this is to declare a collection or your array of objects that we can use and then just map over it using something like lodash.

So the way we can do this is by going this.inputData =and then opening a collection here and putting some javascript objects in here so we got to think of the attributes we need for this object. We're going to need noun we're going to need our placeholder and our input description which is also the same value as the placeholder. So we don't need to change that and then we need our prop title so we know how to reference it to state. So in here let's put placeholder: 'Color'and then for prop: 'color'now let's just copy and paste this a few times and put in 'Noun (Plural)', prop: 'pluralNoun' and so on.

large

Okay so now that we have that in place let's get rid of this and let's actually get rid of the rest of our inputs.

large

Then let's pull this up a little bit and in here in our mad lib input let's replace all of these with the appropriate value so props and in curly braces {props.placeholder} and then down here you put in {props.placeholder}.

large

Now what we can do is utilize lodash to make this a lot easier. So import _ from 'lodash' and if you are saving this like I am you'll notice this is freaking out a little bit because there's a lot of errors in our project as we're kind of reformatting this. So there are no inputs so there's not going to be any and it did that because I put a colon in and saved it but it was an apostrophe. But basically right now let's use lodash to map both of these so if we go underscore dot map and then we type in the lodash map function we can actually map over these pieces of data and render the component each time we do that. So this.inputData and then we can have that data and indexKey and there's a reason I'm naming it indexKey rather than just index like you would normally and I'll show you why. So in here we can we are getting each we're going over our input data so to show that this is working type in console.log(data) and console.log might as well give it a name so 'this is our indexKey' and then you can toss that in there.

large

Now if you save it and going here make sure console is open and wait for it to reload. You'll notice that we go over that data. So placeholder color prop color this is our indexKey zero and so on. So with these pieces of data we can now quickly render out all of our components and this is quite amazing actually. So we can type in my MadlibInput and then we can pass in the data we need to pass in the props. So let's just start with the placeholder and set that equal to data.placeholder and we're going to actually have to put this in curly brackets so data.placeholder. Then let's go on to prop and set this equal to data.prop and that's going to access our prop and our placeholder and then we still need the on change. So let's change that to handleChange is equal to this.handleChange and then we need to throw in our data prop so we actually don't even want to pass in prop as one of our props because we're using it right here immediately right. So what's going on here?Okay, this needs to be parentheses and this does not need to be parentheses and we need to add in the rest of input.

large

All right so that should be working if you hit save and reload the page or wait for it to reload. You'll see our inputs. All right so it looks like our inputs are not rendering. Let's find out why and we already know it's going over this. So what could be the possible reason. All right so the reason, it's not rendering is because we need to return it from this function. Otherwise it's not doing anything.

large

So save that go back to your app reload it and you'll see our inputs and then you'll notice that we have an error that says each child in an array or iterators share a unique key prop. So this goes back to why I was talking about indexKey. So what we need to do is actually say key = indexKey. That will give us a unique key prop because 0 1 2 3 there will always be unique because this position can never be in the same position as go 0 1 2 3. So our indexKey is going to be worth 0 1 2 3. We can even console.log this by saying index our unique key is $[indexKey] then if we reload this we'll see that it is printing out a different number every time. There is no way it's going to ever print out the same number. So that works really well for a unique key and it's also a great way to number our inputs.

large

So let's pass in another prop called index and just set that equal to indexKey + 1 and the reason we do plus 1 is so it doesn't start to zero. So this is one and you might ask why don't we just use key and then in here we call key plus 1 which is exactly what I thought would work when I first started to react. So go ahead and reload that save that and we'll see if that works. You'll notice that it says the key is not defined and that's actually because I didn't type props. So now let's try this and then you'll notice that there is another error. It says key is not a prop trying to access it would result in undefined being returned. If you need to access the same value within the child component you should pass it as a different product. And the reason this is because key is not a prop it's the key of this component. So let's go ahead and just say indexKey and then remove the plus 1 and that should work. So it's not working and that is because we named the index and not index key. To just change that index and reload. So you're seeing it says 1 2 3 4 and that's all great exactly what we want and if you type into these it looks like it's saying the value is undefined. So let's find out why. Let's scroll down to our lodash function and take a look at handleChange. The first thing we want to do is let's just rename this to onChange and then back in our component let's just reference this as props.onChange. The reason this is saying value for state undefined is DD is because we typed in our state we've typed in our new values and it's saying the right value but it's saying undefined because we haven't passed in an input title. So in here if we changed it to a javascript object in this.handleChange we give the value of inputTitle save it and reload and it should work. All right so now if we type them in it says volume for state color is asdf and then you also notice it's printing out a unique key every single time.

large

So let's go ahead and delete that console log statement which is in here and that's because if you remember back in a couple of videos ago we went over the render function and when it runs it's running because we're modifying state every time a state is modified in here or anywhere else in your app. It's going to run render all over again which is how we have access to continuous state active state by state. So that is a functional component and that's how we can greatly reduce the amount of code we are writing so to prove this a little further. Let's go to our design and look at the next inputs when it looks like we need an adjective and noun and number and a number. So back in our code lets just type those as comments, adjective, noun, number, and number and then let's just copy this.

medium

Lets put these in so Adjective, adjectiveTwoand then now Noun and then the nounOne, Numberand numberOneand then Number and numberTwo. Then we're going to change this number and delete this.

medium

Now if you save that and go back to your app wait for it to reload you will notice we have four more inputs. This is really kind of amazing because we only typed in four more lines of code so this is extremely optimized. This is really nice and in a future guide we will actually be optimizing and a little bit more and changing this into its own component and putting it into its own file. So that's an introduction to functional components. So before I end this guide I'm going to talk a little bit more about state and we're going to set the value of our inputs to the correct state. So in our mad lib input. Let's go ahead and type another property. This property is going to be called state and we're going to set it equal to data.state.
Now in our JavaScript objects up here we're just going to pass in another piece of data. Another variable and we can call it state and then give it the appropriate piece of state. So this.state.color let's just copy this and you'll notice if we save that and then we go up here in our input and let's give our value the value of prop.state.

Now if you do this and reload your app then type into one of these inputs you'll notice that changes for every single input which is not what we want but it's important that we look at it and understand why this is happening. So real quick in our completed app if I type in noun and I type in my broskis or something and then generate mad lib you'll notice that it is automatically updating this right here so if I delete this down to broskis. It's down to broskis automatically. I delete the s it's brewski automatically so much like this has the same exact behavior except for in the wrong place. So if I do this it's going to do it across all of these. And if I tried typing in these other ones nothing is going to happen because our input state for each of these components is set to color. And when I change the value of this. It's changing the value of noun 1 and not color so instantly it's setting the state and then it's clearing it back to nothing because this is set to nothing because the value of color is nothing. So let's go back and fix this in our app the way we do this is pretty straightforward we just got to change all these

large

save that reload the page and then see what we get when we type into each of these inputs. So you'll notice if we type in any of these bottom inputs we are getting an error but not the top inputs and you might be wondering why. That's because we haven't declared it up here if you go up to our error it says a component is changing uncontrolled input of type text to be controlled input element should not switch from uncontrolled control or vice versa decide between using controlled or uncontrolled input elements for the lifetime of the component. So in here we just got to verify each of these variables.

medium

We've got to initialize them in our constructor for a state so go ahead and copy adjective 1 and 2, noun 1,
number 1, and number 2.

medium

Now we save this and reload the page you shouldn't get any errors. Sweet we have no errors. It's mapping over to our inputs correctly and everything looks pretty nice. All right so that's it for this guide. Before we end it let's just go ahead and commit our code to GitHub.

git status
git add .
git commit -m "created our first functional component and utilized switching over our input data"
git push origin master

All right so that's it for this video in the next video we will be going a little bit over forms and we will also be introducing the generate mad lib button and styling that button so I'll see in the next video.

Resources

source code