DEV Community

Bipon Biswas
Bipon Biswas

Posted on

Day 2 : React start for Beginner - Component (Class)

Create react project create-react-app counter-app run the command space and provide your application name. So this command creates the react application. And automatically set up the necessary development server babel and web pack. The development server helps us to execute react applications after compilation.

Setting Up the Project (Install Bootstrap)

npm i bootstrap@4.1.1

Import index.js file
import 'bootstrap/dist/css/bootstrap.css';

Into the src folder create a components folder. And add a new file, we call it counter.jsx. Note that here I'm using camel notation. So the first letter of the first word should be lower case.

Your First React Component

import React, { Component } from 'react';

class Counter extends Component {
    state = {

    };
    render() {         
        return ()
     }
}
Enter fullscreen mode Exit fullscreen mode

Initially Counter component showing like that.

render() {         
        return <h1>Hello World</h1>
     }
Enter fullscreen mode Exit fullscreen mode

It's a JSX expression. It's not a string

Import counter component into index.js file
import Counters from './components/counters';

Counter is default export, we don't need curly braces around it.

And finally where we are rendering a React component. Instead of the app component, we're going render our Counter Component

ReactDOM.render(
  <Counters />,
  document.getElementById('root')
);
Enter fullscreen mode Exit fullscreen mode

Embedding Expressions

We need to add property, call it state and set it to an object. State is a special property in React component, and basically it's an object that includes any data that is component needs.

state = {
        count: 0,
    };
Enter fullscreen mode Exit fullscreen mode

Now, I'm going to replace with a span.
So if you want to render the value of the count property here. You would write code like this. This, reference the current object

class Counter extends Component {
    state = {
      count: 0
    };
    render() {         
        return (
           <span>{this.state.count} </span>
         )
     }
}

Enter fullscreen mode Exit fullscreen mode

In between these curly braces we can write any valid JavaScript expressions. An expression is something that produces value. For example, we can write something like 2+2

Now update few things. We can call the function that returns a value. For example let's add a method in this calls it format count.

formatCount(){
        // object destructuring
        const { count } = this.state;
        return count === 0 ? 'Zero' : count;
        // return count === 0 ? <h2>Zero</h2> : count; // jsx expression support also
    }
Enter fullscreen mode Exit fullscreen mode
<span>{this.formatCount()}</span>
Enter fullscreen mode Exit fullscreen mode

Output

Image description

Setting Attributes

How to set in these element. Let's add this image here.

<img src="" alt="" />
Enter fullscreen mode Exit fullscreen mode

To set the value of the source attribute dynamically. So add property in state object.

state = {
        count: 0,
        imageUrl: 'https://picsum.photos/200'
    };
Enter fullscreen mode Exit fullscreen mode

Generate a random 200x200 pixel image. Now back to the image element. Let's replace the quotes with braces. That we can use these braces to render values dynamically.

<img src={this.state.imageUrl} alt="" />
Enter fullscreen mode Exit fullscreen mode

Output

Image description

class attributes

We want to apply a class to this span element, the name of the attribute is not class, it's class name.

<span  className="badge badge-primary m-2">{this.formatCount()}
//<span  className={this.getBadgeClasses()}>{this.formatCount()}</span>
Enter fullscreen mode Exit fullscreen mode

We cannot use class property on an object, because that's a reserve keyword in JavaScript. So name of the attribute in JSX is className. Use a couple of bootstrap classes, one is badge badge-primary

Rendering class dynamically

Out badge is currently blue, but let's change this application such that if the value of count property is 0, we want to render this as yellow, to indicate this some kind of warning, otherwise we want to render it as blue.

    getBadgeClasses() {
        let classes = "badge m-2 badge-";
        classes += this.state.count === 0 ? "warning" : "primary";
        return classes;
    }
Enter fullscreen mode Exit fullscreen mode

Output

Image description

style attributes

In JSX, we have this style attribute that we need to set to a plan JavaScript object. So first we need to add curly braces here, now in between these curly braces we need to pass a plain JavaScript object. Here one way to do this.

    styles = {
        fontSize: 40,
        fontWeight: "bold"
    }
Enter fullscreen mode Exit fullscreen mode
<span style={this.styles}  className={this.getBadgeClasses()}>{this.formatCount()}</span>
Enter fullscreen mode Exit fullscreen mode

another way

<span style={{fontSize: 30}}  className={this.getBadgeClasses()}>{this.formatCount()}</span>
Enter fullscreen mode Exit fullscreen mode

Output

Image description

Rendering List

Tags, we set in to an array of three strings tag1, tag2, tag3

   state = {
        count: 0,
        imageUrl: 'https://picsum.photos/200',
        tags: ['tag 1', 'tag 2', 'tag 3']
    };
Enter fullscreen mode Exit fullscreen mode

Now here in our render method, we want to render these tags using ul, and li elements.

Now if you have worked with Angular, you have seen the ngFor directive, we use that to implement a loop in our templates.
But in React, in JSX expressions, we don't have the concept of loops, because JSX is really not a template engine, it's just simple syntax that will eventually get compiled to react element. So how can we render a bunch of tags here.

We can use the map method. Render something dynamically, so we start with curly braces. We get this.state.tags this is an array, so here have a map method. Now as the argument we need to pass an arrow function, tag goes to now we get each tag and map it to a list item.

<ul>
    {this.state.tags.map((tag) => <li>{tag}</li>)} 
</ul>
Enter fullscreen mode Exit fullscreen mode

So this is how we render a list of items in React.

Output

Image description
In the console, we should see this error. Each child in an array or iterator should have a unique key. Because it needs to uniquely identify. React element in the virtual DOM changes, react wants to quickly figure out what element is changed, and where in the DOM it should make changes to keep the DOM in sync with the virtual DOM.
Image description

So whenever you're using the map method to render a list of items, you need to set a key attribute. So key, we set this to a dynamic value.

<ul>
   {this.state.tags.map((tag) => <li key={tag}>{tag}</li>)} 
</ul>
Enter fullscreen mode Exit fullscreen mode

Conditional Rendering

We have an array of items and we're rendering that in a list. Now here's a list.

New requirement, If this array has at least one element, you want to render that array, in a list, otherwise we want to display a message like there are no tags. How can we implement this?

<ul>
    {this.state.tags.map((tag) => <li key={tag}>{tag}</li>)} 
</ul>
Enter fullscreen mode Exit fullscreen mode

So render elements conditionally. Here's on way to implement the scenario. We can add a separate helper method like renderTags

renderTags(){
if(this.state.tags.length === 0) return <p>There are no tags!</p>;
return <ul>{this.state.tags.map(tag => <li key={tag}>{tag}</li>)}</ul>
 }
Enter fullscreen mode Exit fullscreen mode
{this.state.tags.length === 0 && "Please create a new tag"}
{this.renderTags()} 
Enter fullscreen mode Exit fullscreen mode

Output

Image description

Handling Events

Let's see how we can handle events. So all these React element have property that are based on standard DOM events. For example, here on a button we have a property onClick. We also have onDoubleClick, if you're working with input fields you have onKey onKeypress onKeyUp all those standard DOM events that you're familiar with.

Here let's handle the onClick event. We set this curly braces because we need to pass an expression. Now the way we do this is by defining a method here.

<button onClick={ this.handleIncrement } className="btn btn-secondary btn-sm">+</button>
Enter fullscreen mode Exit fullscreen mode

Note that the name of the event here is case sensitive. So if you use lower case c here you're going to get an error.

    handleIncrement = (product) => {
        console.log("Increment Clicked")
    }
Enter fullscreen mode Exit fullscreen mode

Output

Image description

Reference

Day 1 : React start for Beginner

Discussion (1)

Collapse
tarevcio profile image
Tare-Vcio

It's very easy to know