📜 ⬆️ ⬇️

React Training Course Part 14: Workshop on Class Based Components, Component State

In this part of the translation of the React course, we suggest that you complete a practical task on working with class-based components. After that we will begin to master such an important concept of React, as the state of the components.

image

Part 1: Course Overview, React, ReactDOM, and JSX Reasons
Part 2: Functional Components
Part 3: Component Files, Project Structure
Part 4: Parent and Child Components
Part 5: Getting Started on a TODO Application, Basics of Styling
Part 6: Some of the features of the course, JSX and JavaScript
Part 7: Inline Styles
Part 8: continued work on the TODO application, familiarity with the properties of components
Part 9: Component Properties
Part 10: Workshop on working with the properties of components and styling
Part 11: dynamic markup generation and the map array method
Part 12: workshop, the third stage of work on the TODO application
Part 13: Class Based Components
Part 14: Workshop on Class Based Components, Component State
Part 15: workshops on working with the state of components

Session 25. Workshop. Class Based Components


Original

▍Job


Below is the code that needs to be placed in the index.js file of a standard React application created by create-react-app . Convert the functional components you find in this code into class-based components, and also find and fix a small error.

Code file index.js :

 import React from "react" import ReactDOM from "react-dom" // #1 function App() {   return (       <div>           <Header />           <Greeting />       </div>   ) } // #2 function Header(props) {   return (       <header>           <p>Welcome, {props.username}!</p>       </header>   ) } // #3 function Greeting() {   const date = new Date()   const hours = date.getHours()   let timeOfDay     if (hours < 12) {       timeOfDay = "morning"   } else if (hours >= 12 && hours < 17) {       timeOfDay = "afternoon"   } else {       timeOfDay = "night"   }   return (       <h1>Good {timeOfDay} to you, sir or madam!</h1>   ) } ReactDOM.render(<App />, document.getElementById("root")) 

▍Decision


First, let's take a look at what the application gives out in its original form, opening it in the browser.


The page of the original application in the browser

It can be seen that the top line, which is displayed on the page, looks wrong. After the comma following Welcome, there obviously should be something like a username.

If you analyze the application code, it turns out that this line is output by the Header component, expecting to get the username property that was set when creating its instance. An instance of this component is created in the App component. Having found this out, we can correct the very mistake that was mentioned in the assignment.

It should be noted that the components are usually placed in different files, but in this case we have described them all in one file.

We proceed to the transformation of the functional component App into a component based on a class. To do this, it is enough to bring its code to this form:

 class App extends React.Component {   render() {       return (           <div>               <Header username="vschool"/>               <Greeting />           </div>       )   } } 

The component class name is now in front of it, the extends React.Component command is followed by the extends React.Component , after which, in curly brackets, the class body is described. There must be a render() method that returns what we returned from the functional component. Other components are processed in the same way. Notice the <Header username="vschool"/> construct. Here we pass to the Header component the username property with the value of vschool , thereby correcting the error that exists in the source application.

As you already know, the Header component expects to get the username property, and in a functional component, access to this property is performed using the props.username construction ( props in this case is an argument of the function describing the component). In class-based components, the same looks like this.props.username . Here is the revised code for the Header component:

 class Header extends React.Component {   render() {       return (           <header>               <p>Welcome, {this.props.username}!</p>           </header>       )   } } 

The third component, Greeting , is a bit different. The fact is that in it, before the return command, some calculations are performed. When converting it to a component based on a class, these calculations must be placed in the render() method before the return command. Here is the code for the reworked Greeting component:

 class Greeting extends Component {   render() {       const date = new Date()       const hours = date.getHours()       let timeOfDay             if (hours < 12) {           timeOfDay = "morning"       } else if (hours >= 12 && hours < 17) {           timeOfDay = "afternoon"       } else {           timeOfDay = "night"       }       return (           <h1>Good {timeOfDay} to you, sir or madam!</h1>       )   } } 

Notice that when declaring this component, the following construction was used: class Greeting extends Component . Often they do this for the sake of brevity of code, but in order for this to work, we need to refine the import command react , putting it into this form:

 import React, {Component} from "react" 

Here’s what the redesigned browser page looks like.


Redesigned browser page

As a matter of fact, it looks the same as the page of the original application, and the only noticeable difference between these pages is that the first name of the user is transferred to the Header component.

Here is the complete code for the revised index.js file:

 import React, {Component} from "react" import ReactDOM from "react-dom" // #1 class App extends React.Component {   render() {       return (           <div>               <Header username="vschool"/>               <Greeting />           </div>       )   } } // #2 class Header extends React.Component {   render() {       return (           <header>               <p>Welcome, {this.props.username}!</p>           </header>       )   } } // #3 class Greeting extends Component {   render() {       const date = new Date()       const hours = date.getHours()       let timeOfDay             if (hours < 12) {           timeOfDay = "morning"       } else if (hours >= 12 && hours < 17) {           timeOfDay = "afternoon"       } else {           timeOfDay = "night"       }       return (           <h1>Good {timeOfDay} to you, sir or madam!</h1>       )   } } ReactDOM.render(<App />, document.getElementById("root")) 

If the implementation of this practical task did not cause you difficulties - great. If you are still not fully accustomed to the components based on the classes - take some time to experiment with them. For example, you can again convert components based on classes into functional components, and then perform the inverse transformation.

Lesson 26. Component Status


Original

A state is an incredibly important React concept. If a component needs to store any of its own data and to manage this data (as opposed to the situation when the data is passed to it by the parent component using the property mechanism), the state of the component is used. Today we look at the basic concepts relating to the state of the components.

A state is only data that a component manages. In particular, this means that the component can change this data. At the same time, the properties that the component receives from the parent component that are already familiar to us cannot be changed by the receiving component. They are, according to the React documentation , immutable (immutable). For example, if you try, in a component based on a class, use a construct like this.props.name = "NoName" - we will encounter an error message.

It should be noted that if a certain component needs to work with the state, then it must be a component based on the class. Let's talk about how to equip a component with a state, starting with the following code snippet, which is the contents of the App.js file of a standard project created by create-react-app :

 import React from "react" class App extends React.Component {   render() {       return (           <div>               <h1>Is state important to know?</h1>           </div>       )   } } export default App 

This is what the application page looks like in a browser.


Application page in the browser

To equip a component with a state, you first need to create a class constructor. It looks like a constructor() class method. After this, the component code will look like this:

 class App extends React.Component {   constructor() {         }     render() {       return (           <div>               <h1>Is state important to know?</h1>           </div>       )   } } Constructor() 

This is a special method embedded in JavaScript that is designed to create and initialize objects based on classes. In fact, if you need to initialize something when creating an object, the corresponding operations are performed in the constructor() method.

The first thing to do in the constructor code is to call the parent class constructor. This is done using the super() function. In the constructor of the parent class, some initialization operations can be performed, the results of which will be useful to our object. Here is what the constructor of our class will now look like:

 constructor() {   super() } 

Now, in order to equip a component with a state, we need, in the constructor, to add the state property to the class instance. This property is an object:

 constructor() {   super()   this.state = {} } 

Here we initialized it with an empty object. You can work with the state in the component code using the this.state construction. Add a new property to the state:

 constructor() {   super()   this.state = {       answer: "Yes"   } } 

Now let's think about how to use what is stored in the state, in the code. Recall that the component displays the question Is state important to know? . The state stores the answer to this question. In order to add this answer after the question, you need to do the same as we usually do by adding JavaScript constructs to the JSX code. Namely, you need to add the {this.state.answer} construct to the end of the line. As a result, the complete component code will look like this:

 class App extends React.Component {   constructor() {       super()       this.state = {           answer: "Yes"       }   }     render() {       return (           <div>               <h1>Is state important to know? {this.state.answer}</h1>           </div>       )   } } 

This is how the application page will look like in a browser.


Application page in the browser

Here I would like to note that the state that the component receives during initialization can be changed during the component operation. In addition, components can transfer state to descendant components using the mechanism of working with properties that you already know. For example, in our case, if we assume that there is a certain component ChildComponent , the data from the state can be passed to it like this:

 <ChildComponent answer={this.state.answer}/> 

Until we talk in detail about how to change the data stored in the component state. We only note that when calling the setState() method, which is used to solve this problem, not only the state of the component will be changed, but also the state data passed through the property mechanism to its child components will be updated. In addition, a state change will cause the data from the state displayed on the application page to change automatically.

Results


Today you had the opportunity to work with class-based components. In addition, here began your acquaintance with the concept of the state of the components. The next time you are waiting for practical tasks to work with the state.

Dear readers! If you use React in practice, please tell us how you manage the state of the components. Do you use standard React or something else for this?

Source: https://habr.com/ru/post/438986/