React State and Props
#
WhyThere is just a little bit more you have to understand to write your first React application. If you’ve done the previous lesson, you should now have a great foundation for the next concepts that you will learn. Make sure you pay attention to this lesson because it covers one of the most important concepts to get you started with React.
#
What#
PropsSo far, you’ve learned a lot about components and how to structure your application component-based. But how do we pass values or even functionality between those components? Yes, you guessed it right, the answer is props.
Below, there are two components, MyComponent
and App
. As you can see, MyComponent
is a child component of App
, which passes down a property called title. In this specific example, the title is set to “React”. In MyComponent
, we can access the title (React) that has been passed down with the syntax this.props.title. The curly brackets around it are always needed when you write JavaScript in React.
NOTE: Make sure you pass props to the constructor of the child component (
MyComponent
) as well as thesuper()
method, otherwise you will not be able to access this.props.title inMyComponent
.
In MyComponent:
In App.js:
Now you might be wondering how props work with functions. Believe it or not, they work the same way!
In MyComponent:
In App.js:
There is a little bit more going on here, but in the end, it works exactly as in the example before. First, there is the MyComponent, which is essentially the same. The only thing we added is the { this.props.onButtonClicked }
as an onClick
event to the component. You should already be familiar with this syntax. Now to the App
component.
First, we defined the function onClickBtn
above the render method. After that, we passed this function down to our MyComponent as a property, which we named onButtonClicked (Of course, you could also name it onClickBtn
, and then use the function in MyComponent.js
by the name of onClickBtn
, but we wanted to emphasize that you can rename the functions when passing them around as props). We do that the same way we passed the title value previously. Now the only thing we have to do is bind the method to this; we do that in the constructor method at the top of our component but below the super()
call. The reason we have to bind this keyword when passing a function to another component is that it needs to stay in the same context. So remember, you have to bind this for all functions in all class components when passing them to other components.
As you can see when you are passing many properties or functions to a component, it can get quite exhausting to always refer to them with this.props.someProperty
. Destructuring to the rescue! We can alternatively write the above as follows:
In MyComponent:
Here, we are destructuring title
and onButtonClicked
from this.props
, which lets us refer to them with just their names. Make sure to destructure within the render method when using class components. In functional components (more on those later!), you would destructure outside of the return statement.
#
StateAnother very important concept in React is “state”. In short, all values that can change over time are handled through state.
The following example shows how to define state in React:
In App.js:
In the above component, we declared a piece of state. You always declare state in the constructor of a class component. Keep in mind that this will work differently when we cover functional components later. The setState
method we call sets the state to a new value. In React, state is immutable. This means you should never change state directly because it can lead to unexpected behavior or bugs. What exactly does that mean? Never do something like this: this.state.count = 3
, instead always use the setState
method React provides built-in to modify the state. Keep this in mind, it can save you a lot of debugging when you are getting started with React.
Further, it’s important to note that with class-based components, class methods such as our countUp()
method need to be bound in our constructor (using bind
), so they know what context to operate in. This is a result of how this works in JavaScript.
As you have also seen in the render method, we access the current state through this.state.count
. This syntax should look familiar to you by now because it is the same way we accessed props. And yes, you can also de-structure the state.
#
State and props in functional componentsAs you have learned, React provides the ability to create functional components. They work a little bit differently than the class components we’ve discussed thus far. The concept of props
works mostly the same, with the only difference being that you don’t pass props
as an argument to the constructor, instead you pass it as an argument to the component itself. Another major difference between functional and class components concerning props
is the way you call the props
. You learned that in a class component, the props
that have been passed down from the parent component will be called like so: this.props.someFunction
, however in functional components, we don’t need to call this, so we access props
like so: props.someFunction
. That’s the main difference with props between class and functional components. Let me give you a quick example to emphasize this.
Of course, we can also destructure from props here. By adding this line const {title} = props
above the return statement in MyComponent.js
we can just refer to the title using { title }
.
For the state in functional components, it is a little bit different. Before the end of 2018, developers were not able to access state in functional components at all. Functional components were therefore just used for returning JSX logic. However, with the introduction of React Hooks, this has changed. Now we can set and access state in functional components, and for newer code, they are often preferred over class components. You will be exposed to both kinds of components on the job, requiring us to be very familiar with both. The way React hooks work is the topic of one of the following lectures, so don’t worry about it too much right now. We are setting you up to say “Hey! I remember that” when it’s introduced.
#
Controlled InputsIn React, a common practice when dealing with input
, textarea
, and select
form fields is to control the input values with component state. These are referred to as Controlled Inputs. The idea is to create a binding between a components state and the input's value. When the user updates the input's value, state should be updated. When state is updated, the DOM should be re-rendered and the current input value displayed to the user.
Here is an example:
#
Rendered ListsRendered Lists in React are great ways to render components from array items. Take the following list of names:
We very well might want to display these names as li
elements on the DOM. We can easily do this with a rendered list.
Notice what is placed inside of the ul
. We call map
on the names array, and return a new array where each name string is replaced with a li
displaying the name. The key
prop is important when using rendered lists. It should be a unique value per element, and is used by the ReactDOM to differentiate between items in a list. Although you can use the indices from an array, it is better to use id
values if you have them on your data.
#
HowLet’s practice by recreating a number guessing game in React.
We'll start with the App.jsx
resembling the following:
For our number guessing game, we will need to keep up with four values:
- the number to guess
- the guessed number from the user
- the feedback given to the user after each guess
- the user's score
We will define these values in the constructor of the App
class.
feedback
and guess
are defined as state whereas correctNum
and score
are not. This is because we intend for the DOM to be updated each time the user changes their guess and we give them feedback. We will not need to update the DOM when either we generate the number to guess per game, or their score is changed, so those values are just defined as properties on the App
instance.
Our game will progress as the user submits guesses. We will control the guess input with state and use a form
element to listen for submit
events.
Let's define a method to handle submit
events.
handleGuess
will prevent the default form submission behavior, evaluate the user's guess against the correct number, and update the feedback state.
Now all that is left is to add handleGuess
as the event handler for the form
's onSubmit
prop, bind the this
value for handleGuess
to the App
instance in the constructor, and control the guess input with this.state.guess
.
In render
:
In constructor
:
Awesome! This React Number Guessing Game should be a simple, working version where the user can submit guesses and receive feedback whether their guess was above, below, or correct in relation to the generated number.
#
Takeaways- Props is an object, containing key/value pairs, that is passed from parent to child component
- State is a property that, when updated, should trigger a re-render of a component on the virtual dom
- Object destructuring can be used to prevent repetitive code when referencing prop and state values
- Controlled Inputs are inputs whose
value
andonChange
props are tied to state values - Rendered Lists in React are arrays of JSX elements that can be rendered to the ReactDOM