- Create a Simple JSX Element
- Create a Complex JSX Element
- Add Comments in JSX
- Render HTML Elements to the DOM
- Define an HTML Class in JSX
- Learn About Self-Closing JSX Tags
- Create a Stateless Functional Component
- Create a React Component
- Create a Component with Composition
- Render a Class Component to the DOM
Write a React Component from Scratch- Pass Props to a Stateless Functional Component
- Pass an Array as Props
- Use Default Props
- Use PropTypes to Define the Props You Expect
- Access Props Using this.props
- Review Using Props with Stateless Functional Components
- Create a Stateful Component
- Render State in the User Interface
- Render State in the User Interface Another Way
- Set State with this.setState
- Bind ‘this’ to a Class Method
- Use State to Toggle an Element
- Write a Simple Counter
- Create a Controlled Input
- Create a Controlled Form
- Pass State as Props to Child Components
- Pass a Callback as Props
- Use the Lifecycle Method componentWillMount
- Use the Lifecycle Method componentDidMount
- Add Event Listeners
- Optimize Re-Renders with shouldComponentUpdate
- Introducing Inline Styles
- Add Inline Styles in React
- Use Advanced JavaScript in React Render Method
Create a Simple JSX Element
React is an Open Source view library created and maintained by Facebook. It’s a great tool to render the User Interface (UI) of modern web applications.
React uses a syntax extension of JavaScript called JSX that allows you to write HTML directly within JavaScript. This has several benefits. It lets you use the full programmatic power of JavaScript within HTML, and helps to keep your code readable. For the most part, JSX is similar to the HTML that you have already learned, however there are a few key differences that will be covered throughout these challenges.
For instance, because JSX is a syntactic extension of JavaScript, you can actually write JavaScript directly within JSX. To do this, you simply include the code you want to be treated as JavaScript within curly braces: { ‘this is treated as JavaScript code’ }. Keep this in mind, since it’s used in several future challenges.
However, because JSX is not valid JavaScript, JSX code must be compiled into JavaScript. The transpiler Babel is a popular tool for this process. For your convenience, it’s already added behind the scenes for these challenges. If you happen to write syntactically invalid JSX, you will see the first test in these challenges fail.
It’s worth noting that under the hood the challenges are calling ReactDOM.render(JSX, document.getElementById(‘root’)). This function call is what places your JSX into React’s own lightweight representation of the DOM. React then uses snapshots of its own DOM to optimize updating only specific parts of the actual DOM.
The current code uses JSX to assign a div element to the constant JSX. Replace the div with an h1 element and add the text Hello JSX! inside it.
const JSX = <h1>Hello JSX!</h1>;
Create a Complex JSX Element
The last challenge was a simple example of JSX, but JSX can represent more complex HTML as well.
One important thing to know about nested JSX is that it must return a single element.
This one parent element would wrap all of the other levels of nested elements.
For instance, several JSX elements written as siblings with no parent wrapper element will not transpile.
Here’s an example:
Valid JSX:
<div><p>Paragraph One</p><p>Paragraph Two</p><p>Paragraph Three</p></div>
Invalid JSX:
<p>Paragraph One</p><p>Paragraph Two</p><p>Paragraph Three</p>
Add Comments in JSX
JSX is a syntax that gets compiled into valid JavaScript.
To put comments inside JSX, you use the syntax {/* */} to wrap around the comment text.
Render HTML Elements to the DOM
So far, you’ve learned that JSX is a convenient tool to write readable HTML within JavaScript. With React, we can render this JSX directly to the HTML DOM using React’s rendering API known as ReactDOM.
ReactDOM offers a simple method to render React elements to the DOM which looks like this: ReactDOM.render(componentToRender, targetNode), where the first argument is the React element or component that you want to render, and the second argument is the DOM node that you want to render the component to.
As you would expect, ReactDOM.render() must be called after the JSX element declarations, just like how you must declare variables before using them.
The code editor has a simple JSX component. Use the ReactDOM.render() method to render this component to the page. You can pass defined JSX elements directly in as the first argument and use document.getElementById() to select the DOM node to render them to. There is a div with id=’challenge-node’ available for you to use. Make sure you don’t change the JSX constant.
const JSX = (<div><h1>Hello World</h1><p>Lets render this to the DOM</p></div>);// Change code below this lineReactDOM.render(JSX, document.getElementById('challenge-node'));
Define an HTML Class in JSX
Now that you’re getting comfortable writing JSX, you may be wondering how it differs from HTML.
So far, it may seem that HTML and JSX are exactly the same.
One key difference in JSX is that you can no longer use the word class to define HTML classes. This is because class is a reserved word in JavaScript. Instead, JSX uses className.
In fact, the naming convention for all HTML attributes and event references in JSX become camelCase. For example, a click event in JSX is onClick, instead of onclick. Likewise, onchange becomes onChange. While this is a subtle difference, it is an important one to keep in mind moving forward.
Apply a class of myDiv to the div provided in the JSX code.
const JSX = (<div className="myDiv"><h1>Add a class to this div</h1></div>);
Learn About Self-Closing JSX Tags
Another important way in which JSX differs from HTML is in the idea of the self-closing tag.
In HTML, almost all tags have both an opening and closing tag:
; the closing tag always has a forward slash before the tag name that you are closing. However, there are special instances in HTML called “self-closing tags”, or tags that don’t require both an opening and closing tag before another tag can start.For example the line-break tag can be written as
or as
, but should never be written as
, since it doesn’t contain any content.
In JSX, the rules are a little different. Any JSX element can be written with a self-closing tag, and every element must be closed. The line-break tag, for example, must always be written as
in order to be valid JSX that can be transpiled. A
Create a Stateless Functional Component
Components are the core of React. Everything in React is a component and here you will learn how to create one.
There are two ways to create a React component. The first way is to use a JavaScript function. Defining a component in this way creates a stateless functional component. The concept of state in an application will be covered in later challenges. For now, think of a stateless component as one that can receive data and render it, but does not manage or track changes to that data. (We’ll cover the second way to create a React component in the next challenge.)
To create a component with a function, you simply write a JavaScript function that returns either JSX or null. One important thing to note is that React requires your function name to begin with a capital letter. Here’s an example of a stateless functional component that assigns an HTML class in JSX:
const DemoComponent = function() {return (<div className='customClass' />);};
After being transpiled, the
Because a JSX component represents HTML, you could put several components together to create a more complex HTML page. This is one of the key advantages of the component architecture React provides. It allows you to compose your UI from many separate, isolated components. This makes it easier to build and maintain complex user interfaces.
Create a React Component
The other way to define a React component is with the ES6 class syntax. In the following example, Kitten extends React.Component:
class Kitten extends React.Component {constructor(props) {super(props);}render() {return (<h1>Hi</h1>);}}
This creates an ES6 class Kitten which extends the React.Component class. So the Kitten class now has access to many useful React features, such as local state and lifecycle hooks. Don’t worry if you aren’t familiar with these terms yet, they will be covered in greater detail in later challenges. Also notice the Kitten class has a constructor defined within it that calls super(). It uses super() to call the constructor of the parent class, in this case React.Component. The constructor is a special method used during the initialization of objects that are created with the class keyword. It is best practice to call a component’s constructor with super, and pass props to both. This makes sure the component is initialized properly. For now, know that it is standard for this code to be included. Soon you will see other uses for the constructor as well as props.
Create a Component with Composition
Now we will look at how we can compose multiple React components together. Imagine you are building an app and have created three components: a Navbar, Dashboard, and Footer.
To compose these components together, you could create an App parent component which renders each of these three components as children. To render a component as a child in a React component, you include the component name written as a custom HTML tag in the JSX. For example, in the render method you could write:
return (<App><Navbar /><Dashboard /><Footer /></App>)
When React encounters a custom HTML tag that references another component (a component name wrapped in < /> like in this example), it renders the markup for that component in the location of the tag. This should illustrate the parent/child relationship between the App component and the Navbar, Dashboard, and Footer.
In the code editor, there is a simple functional component called ChildComponent and a class component called ParentComponent. Compose the two together by rendering the ChildComponent within the ParentComponent. Make sure to close the ChildComponent tag with a forward slash.
Note: ChildComponent is defined with an ES6 arrow function because this is a very common practice when using React. However, know that this is just a function. If you aren’t familiar with the arrow function syntax, please refer to the JavaScript section.
const ChildComponent = () => {return (<div><p>I am the child</p></div>);};class ParentComponent extends React.Component {constructor(props) {super(props);}render() {return (<div><h1>I am the parent</h1>{ /* Change code below this line */ }<ChildComponent />{ /* Change code above this line */ }</div>);}};
Render a Class Component to the DOM
You may remember using the ReactDOM API in an earlier challenge to render JSX elements to the DOM. The process for rendering React components will look very similar. The past few challenges focused on components and composition, so the rendering was done for you behind the scenes. However, none of the React code you write will render to the DOM without making a call to the ReactDOM API.
Here’s a refresher on the syntax: ReactDOM.render(componentToRender, targetNode). The first argument is the React component that you want to render. The second argument is the DOM node that you want to render that component within.
React components are passed into ReactDOM.render() a little differently than JSX elements. For JSX elements, you pass in the name of the element that you want to render. However, for React components, you need to use the same syntax as if you were rendering a nested component, for example ReactDOM.render(<ComponentToRender />, targetNode). You use this syntax for both ES6 class components and functional components.
Both the Fruits and Vegetables components are defined for you behind the scenes. Render both components as children of the TypesOfFood component, then render TypesOfFood to the DOM. There is a div with id=’challenge-node’ available for you to use.
class TypesOfFood extends React.Component {constructor(props) {super(props);}render() {return (<div><h1>Types of Food:</h1>{/* Change code below this line */}<Fruits /><Vegetables />{/* Change code above this line */}</div>);}};// Change code below this lineReactDOM.render(<TypesOfFood />, document.getElementById('challenge-node'));
Write a React Component from Scratch
Now that you’ve learned the basics of JSX and React components, it’s time to write a component on your own. React components are the core building blocks of React applications so it’s important to become very familiar with writing them. Remember, a typical React component is an ES6 class which extends React.Component. It has a render method that returns HTML (from JSX) or null. This is the basic form of a React component. Once you understand this well, you will be prepared to start building more complex React projects.
Define a class MyComponent that extends React.Component. Its render method should return a div that contains an h1 tag with the text: My First React Component! in it. Use this text exactly, the case and punctuation matter. Make sure to call the constructor for your component, too.
Render this component to the DOM using ReactDOM.render(). There is a div with id=’challenge-node’ available for you to use.
// Change code below this lineclass MyComponent extends React.Component {constructor(props) {super(props);}render() {return (<div><h1>My First React Component!</h1></div>);}};ReactDOM.render(<MyComponent />, document.getElementById('challenge-node'));
Pass Props to a Stateless Functional Component
The previous challenges covered a lot about creating and composing JSX elements, functional components, and ES6 style class components in React. With this foundation, it’s time to look at another feature very common in React: props. In React, you can pass props, or properties, to child components. Say you have an App component which renders a child component called Welcome which is a stateless functional component. You can pass Welcome a user property by writing:
<App><Welcome user='Mark' /></App>
You use custom HTML attributes created by you and supported by React to be passed to the component. In this case, the created property user is passed to the component Welcome. Since Welcome is a stateless functional component, it has access to this value like so:
const Welcome = (props) => <h1>Hello, {props.user}!</h1>
It is standard to call this value props and when dealing with stateless functional components, you basically consider it as an argument to a function which returns JSX. You can access the value of the argument in the function body. With class components, you will see this is a little different.
There are Calendar and CurrentDate components in the code editor. When rendering CurrentDate from the Calendar component, pass in a property of date assigned to the current date from JavaScript’s Date object. Then access this prop in the CurrentDate component, showing its value within the p tags. Note that for prop values to be evaluated as JavaScript, they must be enclosed in curly brackets, for instance
date={Date()}.
const CurrentDate = (props) => {return (<div>{ /* Change code below this line */ }<p>The current date is: {props.date}</p>{ /* Change code above this line */ }</div>);};class Calendar extends React.Component {constructor(props) {super(props);}render() {return (<div><h3>What date is it?</h3>{ /* Change code below this line */ }<CurrentDate date={Date()}/>{ /* Change code above this line */ }</div>);}};
Pass an Array as Props
The last challenge demonstrated how to pass information from a parent component to a child component as props or properties. This challenge looks at how arrays can be passed as props. To pass an array to a JSX element, it must be treated as JavaScript and wrapped in curly braces.
<ParentComponent><ChildComponent colors={["green", "blue", "red"]} /></ParentComponent>
The child component then has access to the array property colors. Array methods such as join() can be used when accessing the property. const ChildComponent = (props) => <p>{props.colors.join(', ')}</p> This will join all colors array items into a comma separated string and produce: <p>green, blue, red</p> Later, we will learn about other common methods to render arrays of data in React.
There are List and ToDo components in the code editor. When rendering each List from the ToDo component, pass in a tasks property assigned to an array of to-do tasks, for example [“walk dog”, “workout”]. Then access this tasks array in the List component, showing its value within the p element. Use join(“, “) to display the props.tasksarray in the p element as a comma separated list. Today’s list should have at least 2 tasks and tomorrow’s should have at least 3 tasks.
const List = (props) => {{ /* Change code below this line */ }return <p>{props.tasks.join(', ')}</p>{ /* Change code above this line */ }};class ToDo extends React.Component {constructor(props) {super(props);}render() {return (<div><h1>To Do Lists</h1><h2>Today</h2>{ /* Change code below this line */ }<List tasks={['walk dog', 'workout']}/><h2>Tomorrow</h2><List tasks={['walk dog', 'workout', 'dinner']}/>{ /* Change code above this line */ }</div>);}};
Use Default Props
React also has an option to set default props. You can assign default props to a component as a property on the component itself and React assigns the default prop if necessary. This allows you to specify what a prop value should be if no value is explicitly provided. For example, if you declare MyComponent.defaultProps = { location: 'San Francisco' }, you have defined a location prop that’s set to the string San Francisco, unless you specify otherwise. React assigns default props if props are undefined, but if you pass null as the value for a prop, it will remain null.
The code editor shows a ShoppingCart component. Define default props on this component which specify a prop items with a value of 0.
const ShoppingCart = (props) => {return (<div><h1>Shopping Cart Component</h1></div>)};// Change code below this lineShoppingCart.defaultProps = {items: 0};
The ability to set default props is a useful feature in React. The way to override the default props is to explicitly set the prop values for a component.
The ShoppingCart component now renders a child component Items. This Items component has a default prop quantity set to the integer 0. Override the default prop by passing in a value of 10 for quantity.
Note: Remember that the syntax to add a prop to a component looks similar to how you add HTML attributes. However, since the value for quantity is an integer, it won’t go in quotes but it should be wrapped in curly braces. For example, {100}. This syntax tells JSX to interpret the value within the braces directly as JavaScript.
const Items = (props) => {return <h1>Current Quantity of Items in Cart: {props.quantity}</h1>}Items.defaultProps = {quantity: 0}class ShoppingCart extends React.Component {constructor(props) {super(props);}render() {{ /* Change code below this line */ }return <Items quantity={10}/>{ /* Change code above this line */ }}};
Use PropTypes to Define the Props You Expect
React provides useful type-checking features to verify that components receive props of the correct type. For example, your application makes an API call to retrieve data that you expect to be in an array, which is then passed to a component as a prop. You can set propTypes on your component to require the data to be of type array. This will throw a useful warning when the data is of any other type.
It’s considered a best practice to set propTypes when you know the type of a prop ahead of time. You can define a propTypes property for a component in the same way you defined defaultProps. Doing this will check that props of a given key are present with a given type. Here’s an example to require the type function for a prop called handleClick:
MyComponent.propTypes = { handleClick: PropTypes.func.isRequired }
In the example above, the PropTypes.func part checks that handleClick is a function. Adding isRequired tells React that handleClick is a required property for that component. You will see a warning if that prop isn’t provided. Also notice that func represents function. Among the seven JavaScript primitive types, function and boolean (written as bool) are the only two that use unusual spelling. In addition to the primitive types, there are other types available. For example, you can check that a prop is a React element. Please refer to the documentation for all of the options.
Note: As of React v15.5.0, PropTypes is imported independently from React, like this: import PropTypes from ‘prop-types’;
Define propTypes for the Items component to require quantity as a prop and verify that it is of type number.
const Items = (props) => {return <h1>Current Quantity of Items in Cart: {props.quantity}</h1>};// Change code below this lineItems.propTypes = {quantity: PropTypes.number.isRequired}// Change code above this lineItems.defaultProps = {quantity: 0};class ShoppingCart extends React.Component {constructor(props) {super(props);}render() {return <Items />}};
Access Props Using this.props
The last several challenges covered the basic ways to pass props to child components. But what if the child component that you’re passing a prop to is an ES6 class component, rather than a stateless functional component? The ES6 class component uses a slightly different convention to access props.
Anytime you refer to a class component within itself, you use the this keyword. To access props within a class component, you preface the code that you use to access it with this. For example, if an ES6 class component has a prop called data, you write {this.props.data} in JSX.
Render an instance of the Welcome component in the parent component App. Here, give Welcome a prop of name and assign it a value of a string. Within the child, Welcome, access the name prop within the strong tags.
class App extends React.Component {constructor(props) {super(props);}render() {return (<div>{ /* Change code below this line */ }<Welcome name='Wayne'/>{ /* Change code above this line */ }</div>);}};class Welcome extends React.Component {constructor(props) {super(props);}render() {return (<div>{ /* Change code below this line */ }<p>Hello, <strong>{this.props.name}</strong>!</p>{ /* Change code above this line */ }</div>);}};
Review Using Props with Stateless Functional Components
Except for the last challenge, you’ve been passing props to stateless functional components. These components act like pure functions. They accept props as input and return the same view every time they are passed the same props. You may be wondering what state is, and the next challenge will cover it in more detail. Before that, here’s a review of the terminology for components.
A stateless functional component is any function you write which accepts props and returns JSX. A stateless component, on the other hand, is a class that extends React.Component, but does not use internal state (covered in the next challenge). Finally, a stateful component is a class component that does maintain its own internal state. You may see stateful components referred to simply as components or React components.
A common pattern is to try to minimize statefulness and to create stateless functional components wherever possible. This helps contain your state management to a specific area of your application. In turn, this improves development and maintenance of your app by making it easier to follow how changes to state affect its behavior.
The code editor has a CampSite component that renders a Camper component as a child. Define the Camper component and assign it default props of { name: ‘CamperBot’ }. Inside the Camper component, render any code that you want, but make sure to have one p element that includes only the name value that is passed in as a prop. Finally, define propTypes on the Camper component to require name to be provided as a prop and verify that it is of type string.
class CampSite extends React.Component {constructor(props) {super(props);}render() {return (<div><Camper/></div>);}};// Change code below this lineconst Camper = (props) => {return (<div><p>{props.name}</p></div>);};Camper.defaultProps = {name: 'CamperBot'};Camper.propTypes = {name: PropTypes.string.isRequired};
Create a Stateful Component
One of the most important topics in React is state. State consists of any data your application needs to know about, that can change over time. You want your apps to respond to state changes and present an updated UI when necessary. React offers a nice solution for the state management of modern web applications.
You create state in a React component by declaring a state property on the component class in its constructor. This initializes the component with state when it is created. The state property must be set to a JavaScript object. Declaring it looks like this:
this.state = {}
You have access to the state object throughout the life of your component. You can update it, render it in your UI, and pass it as props to child components. The state object can be as complex or as simple as you need it to be. Note that you must create a class component by extending React.Component in order to create state like this.
There is a component in the code editor that is trying to render a name property from its state. However, there is no state defined. Initialize the component with state in the constructor and assign your name to a property of name.
class StatefulComponent extends React.Component {constructor(props) {super(props);// Only change code below this linethis.state = {name: 'Wayne'}// Only change code above this line}render() {return (<div><h1>{this.state.name}</h1></div>);}};
Render State in the User Interface
Once you define a component’s initial state, you can display any part of it in the UI that is rendered. If a component is stateful, it will always have access to the data in state in its render() method. You can access the data with this.state.
If you want to access a state value within the return of the render method, you have to enclose the value in curly braces.
state is one of the most powerful features of components in React. It allows you to track important data in your app and render a UI in response to changes in this data. If your data changes, your UI will change. React uses what is called a virtual DOM, to keep track of changes behind the scenes. When state data updates, it triggers a re-render of the components using that data - including child components that received the data as a prop. React updates the actual DOM, but only where necessary. This means you don’t have to worry about changing the DOM. You simply declare what the UI should look like.
Note that if you make a component stateful, no other components are aware of its state. Its state is completely encapsulated, or local to that component, unless you pass state data to a child component as props. This notion of encapsulated state is very important because it allows you to write certain logic, then have that logic contained and isolated in one place in your code.
In the code editor, MyComponent is already stateful. Define an h1 tag in the component’s render method which renders the value of name from the component’s state.
Note: The h1 should only render the value from state and nothing else. In JSX, any code you write with curly braces { } will be treated as JavaScript. So to access the value from state just enclose the reference in curly braces.
class MyComponent extends React.Component {constructor(props) {super(props);this.state = {name: 'freeCodeCamp'}}render() {return (<div>{ /* Change code below this line */ }<h1>{this.state.name}</h1>{ /* Change code above this line */ }</div>);}};
Render State in the User Interface Another Way
There is another way to access state in a component. In the render() method, before the return statement, you can write JavaScript directly. For example, you could declare functions, access data from state or props, perform computations on this data, and so on. Then, you can assign any data to variables, which you have access to in the return statement.
In the MyComponent render method, define a const called name and set it equal to the name value in the component’s state. Because you can write JavaScript directly in this part of the code, you don’t have to enclose this reference in curly braces.
Next, in the return statement, render this value in an h1 tag using the variable name. Remember, you need to use the JSX syntax (curly braces for JavaScript) in the return statement.
class MyComponent extends React.Component {constructor(props) {super(props);this.state = {name: 'freeCodeCamp'}}render() {// Change code below this lineconst name = this.state.name;// Change code above this linereturn (<div>{ /* Change code below this line */ }<h1>{name}</h1>{ /* Change code above this line */ }</div>);}};
Set State with this.setState
The previous challenges covered component state and how to initialize state in the constructor. There is also a way to change the component’s state. React provides a method for updating component state called setState. You call the setState method within your component class like so: this.setState(), passing in an object with key-value pairs. The keys are your state properties and the values are the updated state data. For instance, if we were storing a username in state and wanted to update it, it would look like this:
this.setState({username: 'Lewis'});
React expects you to never modify state directly, instead always use this.setState() when state changes occur. Also, you should note that React may batch multiple state updates in order to improve performance. What this means is that state updates through the setState method can be asynchronous. There is an alternative syntax for the setState method which provides a way around this problem. This is rarely needed but it’s good to keep it in mind! Please consult the React documentation for further details.
There is a button element in the code editor which has an onClick() handler. This handler is triggered when the button receives a click event in the browser, and runs the handleClick method defined on MyComponent. Within the handleClick method, update the component state using this.setState(). Set the name property in state to equal the string React Rocks!.
Click the button and watch the rendered state update. Don’t worry if you don’t fully understand how the click handler code works at this point. It’s covered in upcoming challenges.
class MyComponent extends React.Component {constructor(props) {super(props);this.state = {name: 'Initial State'};this.handleClick = this.handleClick.bind(this);}handleClick() {// Change code below this linethis.setState({name: 'React Rocks!'});// Change code above this line}render() {return (<div><button onClick={this.handleClick}>Click Me</button><h1>{this.state.name}</h1></div>);}};
Bind ‘this’ to a Class Method
In addition to setting and updating state, you can also define methods for your component class. A class method typically needs to use the this keyword so it can access properties on the class (such as state and props) inside the scope of the method. There are a few ways to allow your class methods to access this.
One common way is to explicitly bind this in the constructor so this becomes bound to the class methods when the component is initialized. You may have noticed the last challenge used this.handleClick = this.handleClick.bind(this) for its handleClick method in the constructor. Then, when you call a function like this.setState() within your class method, this refers to the class and will not be undefined.
Note: The this keyword is one of the most confusing aspects of JavaScript but it plays an important role in React. Although its behavior here is totally normal, these lessons aren’t the place for an in-depth review of this so please refer to other lessons if the above is confusing!
The code editor has a component with a state that keeps track of the text. It also has a method which allows you to set the text to You clicked!. However, the method doesn’t work because it’s using the this keyword that is undefined. Fix it by explicitly binding this to the handleClick() method in the component’s constructor.
Next, add a click handler to the button element in the render method. It should trigger the handleClick() method when the button receives a click event. Remember that the method you pass to the onClick handler needs curly braces because it should be interpreted directly as JavaScript.
Once you complete the above steps you should be able to click the button and see You clicked!.
class MyComponent extends React.Component {constructor(props) {super(props);this.state = {text: "Hello"};// Change code below this linethis.handleClick = this.handleClick.bind(this);// Change code above this line}handleClick() {this.setState({text: "You clicked!"});}render() {return (<div>{ /* Change code below this line */ }<button onClick={this.handleClick}>Click Me</button>{ /* Change code above this line */ }<h1>{this.state.text}</h1></div>);}};
Use State to Toggle an Element
Sometimes you might need to know the previous state when updating the state. However, state updates may be asynchronous - this means React may batch multiple setState() calls into a single update. This means you can’t rely on the previous value of this.state or this.props when calculating the next value. So, you should not use code like this:
this.setState({counter: this.state.counter + this.props.increment});
Instead, you should pass setState a function that allows you to access state and props. Using a function with setState guarantees you are working with the most current values of state and props. This means that the above should be rewritten as:
this.setState((state, props) => ({counter: state.counter + props.increment}));
You can also use a form without props if you need only the state:
this.setState(state => ({counter: state.counter + 1}));
Note that you have to wrap the object literal in parentheses, otherwise JavaScript thinks it’s a block of code.
MyComponent has a visibility property which is initialized to false. The render method returns one view if the value of visibility is true, and a different view if it is false.
Currently, there is no way of updating the visibility property in the component’s state. The value should toggle back and forth between true and false. There is a click handler on the button which triggers a class method called toggleVisibility(). Pass a function to setState to define this method so that the state of visibility toggles to the opposite value when the method is called. If visibility is false, the method sets it to true, and vice versa.
Finally, click the button to see the conditional rendering of the component based on its state.
Hint: Don’t forget to bind the this keyword to the method in the constructor!
class MyComponent extends React.Component {constructor(props) {super(props);this.state = {visibility: false};// Change code below this linethis.toggleVisibility = this.toggleVisibility.bind(this);// Change code above this line}// Change code below this linetoggleVisibility() {this.setState(state => ({visibility: !state.visibility}))}// Change code above this linerender() {if (this.state.visibility) {return (<div><button onClick={this.toggleVisibility}>Click Me</button><h1>Now you see me!</h1></div>);} else {return (<div><button onClick={this.toggleVisibility}>Click Me</button></div>);}}}
Write a Simple Counter
You can design a more complex stateful component by combining the concepts covered so far. These include initializing state, writing methods that set state, and assigning click handlers to trigger these methods.
The Counter component keeps track of a count value in state. There are two buttons which call methods increment() and decrement(). Write these methods so the counter value is incremented or decremented by 1 when the appropriate button is clicked. Also, create a reset() method so when the reset button is clicked, the count is set to 0.
Note: Make sure you don’t modify the classNames of the buttons. Also, remember to add the necessary bindings for the newly-created methods in the constructor.
class Counter extends React.Component {constructor(props) {super(props);this.state = {count: 0};// Change code below this linethis.increment = this.increment.bind(this);this.decrement = this.decrement.bind(this);this.reset = this.reset.bind(this);// Change code above this line}// Change code below this lineincrement() {this.setState(state => ({count: state.count + 1}))}decrement() {this.setState(state => ({count: state.count - 1}))}reset() {this.setState(state => ({count: 0}))}// Change code above this linerender() {return (<div><button className='inc' onClick={this.increment}>Increment!</button><button className='dec' onClick={this.decrement}>Decrement!</button><button className='reset' onClick={this.reset}>Reset</button><h1>Current Count: {this.state.count}</h1></div>);}};
Create a Controlled Input
Your application may have more complex interactions between state and the rendered UI. For example, form control elements for text input, such as input and textarea, maintain their own state in the DOM as the user types. With React, you can move this mutable state into a React component’s state. The user’s input becomes part of the application state, so React controls the value of that input field. Typically, if you have React components with input fields the user can type into, it will be a controlled input form.
The code editor has the skeleton of a component called ControlledInput to create a controlled input element. The component’s state is already initialized with an input property that holds an empty string. This value represents the text a user types into the input field.
First, create a method called handleChange() that has a parameter called event. When the method is called, it receives an event object that contains a string of text from the input element. You can access this string with event.target.value inside the method. Update the input property of the component’s state with this new string.
In the render method, create the input element above the h4 tag. Add a value attribute which is equal to the input property of the component’s state. Then add an onChange() event handler set to the handleChange() method.
When you type in the input box, that text is processed by the handleChange() method, set as the input property in the local state, and rendered as the value in the input box on the page. The component state is the single source of truth regarding the input data.
Last but not least, don’t forget to add the necessary bindings in the constructor.
class ControlledInput extends React.Component {constructor(props) {super(props);this.state = {input: ''};// Change code below this linethis.handleChange = this.handleChange.bind(this);// Change code above this line}// Change code below this linehandleChange(event) {this.setState({input: event.target.value})}// Change code above this linerender() {return (<div>{ /* Change code below this line */}<input value={this.state.input} onChange={this.handleChange} />{ /* Change code above this line */}<h4>Controlled Input:</h4><p>{this.state.input}</p></div>);}};
Create a Controlled Form
The last challenge showed that React can control the internal state for certain elements like input and textarea, which makes them controlled components. This applies to other form elements as well, including the regular HTML form element.
The MyForm component is set up with an empty form with a submit handler. The submit handler will be called when the form is submitted.
We’ve added a button which submits the form. You can see it has the type set to submit indicating it is the button controlling the form. Add the input element in the form and set its value and onChange() attributes like the last challenge. You should then complete the handleSubmit method so that it sets the component state property submit to the current input value in the local state.
Note: You also must call event.preventDefault() in the submit handler, to prevent the default form submit behavior which will refresh the web page. For camper convenience, the default behavior has been disabled here to prevent refreshes from resetting challenge code.
Finally, create an h1 tag after the form which renders the submit value from the component’s state. You can then type in the form and click the button (or press enter), and you should see your input rendered to the page.
class MyForm extends React.Component {constructor(props) {super(props);this.state = {input: '',submit: ''};this.handleChange = this.handleChange.bind(this);this.handleSubmit = this.handleSubmit.bind(this);}handleChange(event) {this.setState({input: event.target.value});}handleSubmit(event) {// Change code below this lineevent.preventDefault();this.setState({submit: this.state.input});// Change code above this line}render() {return (<div><form onSubmit={this.handleSubmit}>{/* Change code below this line */}<input value={this.state.input} onChange={this.handleChange}/>{/* Change code above this line */}<button type='submit' onClick={this.handleSubmit}>Submit!</button></form>{/* Change code below this line */}<h1>{this.state.submit}</h1>{/* Change code above this line */}</div>);}}
Pass State as Props to Child Components
You saw a lot of examples that passed props to child JSX elements and child React components in previous challenges. You may be wondering where those props come from. A common pattern is to have a stateful component containing the state important to your app, that then renders child components. You want these components to have access to some pieces of that state, which are passed in as props.
For example, maybe you have an App component that renders a Navbar, among other components. In your App, you have state that contains a lot of user information, but the Navbar only needs access to the user’s username so it can display it. You pass that piece of state to the Navbar component as a prop.
This pattern illustrates some important paradigms in React. The first is unidirectional data flow. State flows in one direction down the tree of your application’s components, from the stateful parent component to child components. The child components only receive the state data they need. The second is that complex stateful apps can be broken down into just a few, or maybe a single, stateful component. The rest of your components simply receive state from the parent as props, and render a UI from that state. It begins to create a separation where state management is handled in one part of code and UI rendering in another. This principle of separating state logic from UI logic is one of React’s key principles. When it’s used correctly, it makes the design of complex, stateful applications much easier to manage.
The MyApp component is stateful and renders a Navbar component as a child. Pass the name property in its state down to the child component, then show the name in the h1 tag that’s part of the Navbar render method. name should appear after the text Hello, my name is:.
class MyApp extends React.Component {constructor(props) {super(props);this.state = {name: 'CamperBot'}}render() {return (<div>{/* Change code below this line */}<Navbar name={this.state.name}/>{/* Change code above this line */}</div>);}};class Navbar extends React.Component {constructor(props) {super(props);}render() {return (<div>{/* Change code below this line */}<h1>Hello, my name is: {this.props.name}</h1>{/* Change code above this line */}</div>);}};
Pass a Callback as Props
You can pass state as props to child components, but you’re not limited to passing data. You can also pass handler functions or any method that’s defined on a React component to a child component. This is how you allow child components to interact with their parent components. You pass methods to a child just like a regular prop. It’s assigned a name and you have access to that method name under this.props in the child component.
There are three components outlined in the code editor. The MyApp component is the parent that will render the GetInput and RenderInput child components. Add the GetInput component to the render method in MyApp, then pass it a prop called input assigned to inputValue from MyApp’s state. Also create a prop called handleChange and pass the input handler handleChange to it.
Next, add RenderInput to the render method in MyApp, then create a prop called input and pass the inputValue from state to it. Once you are finished you will be able to type in the input field in the GetInput component, which then calls the handler method in its parent via props. This updates the input in the state of the parent, which is passed as props to both children. Observe how the data flows between the components and how the single source of truth remains the state of the parent component. Admittedly, this example is a bit contrived, but should serve to illustrate how data and callbacks can be passed between React components.
class MyApp extends React.Component {constructor(props) {super(props);this.state = {inputValue: ''}this.handleChange = this.handleChange.bind(this);}handleChange(event) {this.setState({inputValue: event.target.value});}render() {return (<div>{ /* Change code below this line */ }<GetInput input={this.state.inputValue} handleChange={this.handleChange}/><RenderInput input={this.state.inputValue}/>{ /* Change code above this line */ }</div>);}};class GetInput extends React.Component {constructor(props) {super(props);}render() {return (<div><h3>Get Input:</h3><inputvalue={this.props.input}onChange={this.props.handleChange}/></div>);}};class RenderInput extends React.Component {constructor(props) {super(props);}render() {return (<div><h3>Input Render:</h3><p>{this.props.input}</p></div>);}};
Use the Lifecycle Method componentWillMount
React components have several special methods that provide opportunities to perform actions at specific points in the lifecycle of a component. These are called lifecycle methods, or lifecycle hooks, and allow you to catch components at certain points in time. This can be before they are rendered, before they update, before they receive props, before they unmount, and so on. Here is a list of some of the main lifecycle methods: componentWillMount() componentDidMount() shouldComponentUpdate() componentDidUpdate() componentWillUnmount() The next several lessons will cover some of the basic use cases for these lifecycle methods.
Note: The componentWillMount Lifecycle method will be deprecated in a future version of 16.X and removed in version 17. (Source)
The componentWillMount() method is called before the render() method when a component is being mounted to the DOM. Log something to the console within componentWillMount() - you may want to have your browser console open to see the output.
class MyComponent extends React.Component {constructor(props) {super(props);}componentWillMount() {// Change code below this lineconsole.log('hello')// Change code above this line}render() {return <div />}};
Use the Lifecycle Method componentDidMount
Most web developers, at some point, need to call an API endpoint to retrieve data. If you’re working with React, it’s important to know where to perform this action.
The best practice with React is to place API calls or any calls to your server in the lifecycle method componentDidMount(). This method is called after a component is mounted to the DOM. Any calls to setState() here will trigger a re-rendering of your component. When you call an API in this method, and set your state with the data that the API returns, it will automatically trigger an update once you receive the data.
There is a mock API call in componentDidMount(). It sets state after 2.5 seconds to simulate calling a server to retrieve data. This example requests the current total active users for a site. In the render method, render the value of activeUsers in the h1 after the text Active Users:. Watch what happens in the preview, and feel free to change the timeout to see the different effects.
class MyComponent extends React.Component {constructor(props) {super(props);this.state = {activeUsers: null};}componentDidMount() {setTimeout(() => {this.setState({activeUsers: 1273});}, 2500);}render() {return (<div>{/* Change code below this line */}<h1>Active Users: { this.state.activeUsers }</h1>{/* Change code above this line */}</div>);}}
Add Event Listeners
The componentDidMount() method is also the best place to attach any event listeners you need to add for specific functionality. React provides a synthetic event system which wraps the native event system present in browsers. This means that the synthetic event system behaves exactly the same regardless of the user’s browser - even if the native events may behave differently between different browsers.
You’ve already been using some of these synthetic event handlers such as onClick(). React’s synthetic event system is great to use for most interactions you’ll manage on DOM elements. However, if you want to attach an event handler to the document or window objects, you have to do this directly.
Attach an event listener in the componentDidMount() method for keydown events and have these events trigger the callback handleKeyPress(). You can use document.addEventListener() which takes the event (in quotes) as the first argument and the callback as the second argument.
Then, in componentWillUnmount(), remove this same event listener. You can pass the same arguments to document.removeEventListener(). It’s good practice to use this lifecycle method to do any clean up on React components before they are unmounted and destroyed. Removing event listeners is an example of one such clean up action.
class MyComponent extends React.Component {constructor(props) {super(props);this.state = {message: ''};this.handleEnter = this.handleEnter.bind(this);this.handleKeyPress = this.handleKeyPress.bind(this);}// Change code below this linecomponentDidMount() {document.addEventListener('keydown', this.handleKeyPress)}componentWillUnmount() {document.removeEventListener('keydown', this.handleKeyPress)}// Change code above this linehandleEnter() {this.setState((state) => ({message: state.message + 'You pressed the enter key! '}));}handleKeyPress(event) {if (event.keyCode === 13) {this.handleEnter();}}render() {return (<div><h1>{this.state.message}</h1></div>);}};
Optimize Re-Renders with shouldComponentUpdate
So far, if any component receives new state or new props, it re-renders itself and all its children. This is usually okay. But React provides a lifecycle method you can call when child components receive new state or props, and declare specifically if the components should update or not. The method is shouldComponentUpdate(), and it takes nextProps and nextState as parameters.
This method is a useful way to optimize performance. For example, the default behavior is that your component re-renders when it receives new props, even if the props haven’t changed. You can use shouldComponentUpdate() to prevent this by comparing the props. The method must return a boolean value that tells React whether or not to update the component. You can compare the current props (this.props) to the next props (nextProps) to determine if you need to update or not, and return true or false accordingly.
The shouldComponentUpdate() method is added in a component called OnlyEvens. Currently, this method returns true so OnlyEvens re-renders every time it receives new props. Modify the method so OnlyEvens updates only if the value of its new props is even. Click the Add button and watch the order of events in your browser’s console as the lifecycle hooks are triggered.
class OnlyEvens extends React.Component {constructor(props) {super(props);}shouldComponentUpdate(nextProps, nextState) {console.log('Should I update?');// Change code below this linereturn nextProps.value % 2 === 0 ? true: false;// Change code above this line}componentDidUpdate() {console.log('Component re-rendered.');}render() {return <h1>{this.props.value}</h1>;}}class Controller extends React.Component {constructor(props) {super(props);this.state = {value: 0};this.addValue = this.addValue.bind(this);}addValue() {this.setState(state => ({value: state.value + 1}));}render() {return (<div><button onClick={this.addValue}>Add</button><OnlyEvens value={this.state.value} /></div>);}}
Introducing Inline Styles
There are other complex concepts that add powerful capabilities to your React code. But you may be wondering about the more simple problem of how to style those JSX elements you create in React. You likely know that it won’t be exactly the same as working with HTML because of the way you apply classes to JSX elements.
If you import styles from a stylesheet, it isn’t much different at all. You apply a class to your JSX element using the className attribute, and apply styles to the class in your stylesheet. Another option is to apply inline styles, which are very common in ReactJS development.
You apply inline styles to JSX elements similar to how you do it in HTML, but with a few JSX differences. Here’s an example of an inline style in HTML:
<div style="color: yellow; font-size: 16px">Mellow Yellow</div>
JSX elements use the style attribute, but because of the way JSX is transpiled, you can’t set the value to a string. Instead, you set it equal to a JavaScript object. Here’s an example:
<div style={{color: "yellow", fontSize: 16}}>Mellow Yellow</div>
Notice how we camelCase the fontSize property? This is because React will not accept kebab-case keys in the style object. React will apply the correct property name for us in the HTML.
Add Inline Styles in React
You may have noticed in the last challenge that there were several other syntax differences from HTML inline styles in addition to the style attribute set to a JavaScript object. First, the names of certain CSS style properties use camel case. For example, the last challenge set the size of the font with fontSize instead of font-size. Hyphenated words like font-size are invalid syntax for JavaScript object properties, so React uses camel case. As a rule, any hyphenated style properties are written using camel case in JSX.
All property value length units (like height, width, and fontSize) are assumed to be in px unless otherwise specified. If you want to use em, for example, you wrap the value and the units in quotes, like {fontSize: “4em”}. Other than the length values that default to px, all other property values should be wrapped in quotes.
If you have a large set of styles, you can assign a style object to a constant to keep your code organized. Declare your styles constant as a global variable at the top of the file. Initialize styles constant and assign an object with three style properties and their values to it. Give the div a color of purple, a font-size of 40, and a border of 2px solid purple. Then set the style attribute equal to the styles constant.
const styles = {color: "purple",fontSize: 40,border: "2px solid purple"}// Change code above this lineclass Colorful extends React.Component {render() {// Change code below this linereturn (<div style={styles}>Style Me!</div>);// Change code above this line}};
