Learn React - Part 3 - Components, State and Props
Tags: react, javascript, webdev
Published: 2018-09-25 13:24:59

---
title: Learn React - Part 3 - Components, State and Props
published: true
description: Learn React - learn how to create components in React, using props and state to pass data between them
tags: react, reactjs, javascript, web development
canonical_url: http://felipegalvao.com.br/blog/2018/09/24/learn-react-components-state-and-props/
series: Learn React
---

<a href="http://felipegalvao.com.br/blog/2018/09/24/learn-react-components-state-and-props/" rel="noopener">Originally published on my blog</a>

Hey folks. <a href="https://dev.to/felipegalvao/learn-react---part-2---getting-to-know-jsx-2gfl">In our last Learn React post</a>, we talked about JSX, the Javascript syntax extension that makes it easier to build interfaces with React, leading to code that seems like a mix of Javascript and HTML.

In this post, we will talk about one of the coolest concepts of React, components.  We'll learn how to create components, import them and organize your application's data around these components.

As an example, we will create a simple counter with buttons to increment and decrement. This simple application will allow us to put into practice all the concepts related to components, state and props.

Again, we will use the setup that we worked on the first post of the Learn React series. You can <a href="https://dev.to/felipegalvao/simple-setup-for-a-react-application-with-webpack-4--css--sass-bef">click here</a> to open it, where you can find the Github repository (or you can just <a href="https://github.com/felipegalvao/webpack-4-react-boilerplate" rel="noopener" target="_blank">click here</a> to access it directly), that you can clone and keep up with this post.

<h2>Components</h2>

As usual, I'll put the basic code that we will start from here. This is what he have right now, if you cloned the repository indicated:

```javascript
import React from "react";
import ReactDOM from "react-dom";

const Index = () => {
  return <div>Hello React!</div>;
};

ReactDOM.render(<Index />, document.getElementById("index"));
```

Ok, the first thing that you need to know is that, using the code above, you already created your first component. When we define `Index` and make it return a JSX element, we use one of the two main ways of creating a component, which is, through a function. Well, let's start to organize our app moving this `Index` component to it's own file. We will have a main component, where we will import and use the others that we will create in this post. First, inside of the `src` folder, we will create the `components` folder, and then, inside of this folder, we will create `App.js` file. This will be our main component. Note that the name of this file is not a rule, you don't need to call it `App.js`, this is just a personal preference:

```javascript
import React from "react";
import ReactDOM from "react-dom";

const App = () => {
  return <div>Hello React!</div>;
};

export default App;
```

Now, let's import this component and use it. In our `index.js` file, located inside of the `src` folder, we will remove the `Index` definition and then import the `App` component that we just created.  We will then, pass it to the `render` method:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import App from "./components/App";

ReactDOM.render(<App />, document.getElementById("index"));
```

If your Webpack server is not running yet, run `yarn run start` in your terminal, and then open your browser in <a href="http://localhost:8080/">http://localhost:8080/</a> (or wait for it to open automatically, depending on your Webpack setup), and marvel as your application is unchanged. That is expected, since we didn't changed anything yet, we just moved some stuff around, getting one component into it's own file.

Now, let's create a new component, which will be responsible for showing the current count. In this first step, we will define the current count manually, but we will soon learn how to make it dynamic. First, let's create the `CountDisplay.js` file inside of the `components` folder. This is the initial code for this file / component:

```javascript
import React from "react";
import ReactDOM from "react-dom";

const CountDisplay = () => {
  return <p>The count is 0</p>
};

export default CountDisplay;
```

As we saw in our last post regarding JSX, we can include the value of a variable inside of an element, using `curly braces ({})`. But what if we could pass the information to this component about the current count value.

<h2>Props</h2>

Props, an abbreviation for properties is basically data that we pass to the component. It can be a string, a number, even a function. This value can then be used by the component that receives it. First, we pass the data we want to the component, defining it as an attribute, but with the name that we want. Let's pass the `currentCount` to the `CountDisplay` component, that is being called in the `App.js` file. For a numeric value, we pass it inside curly braces. Let's see how it will look like.:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import CountDisplay from "./CountDisplay";

const App = (props) => {
  return <CountDisplay 
    currentCount={3}
  />;
};

export default App;
```

Now, let's grab this value inside the component that received it, `CountDisplay`. For that, the first thing we need to do is include `props` as an argument to the function that defines the component. Then, we will have access to whatever props we passed to this component. Let's run a `console.log` to see what the `props` looks like. the code in the `CountDisplay.js` file will be like this:

```javascript
import React from "react";
import ReactDOM from "react-dom";

const CountDisplay = (props) => {
  console.log(props);
  return <p>The count is 0</p>;
};

export default CountDisplay;
```

As you can notice when you refresh your browser tab and open its console, what we have is an object with the `countDisplay prop` that we just passed to this component. Let's do a quick test, passing an additional `prop` to this component, which will be like this:

```javascript
const App = (props) => {
  return <CountDisplay 
    currentCount={3}
    name="Felipe"
  />;
};
```

When you refresh your browser tab again, you will see in your browser's console the `props` object with values for `currentCount` and `name`, the `props` that we passed to this component.

Now we can remove the line where we do the `console.log` and also the line where we pass the `name prop`, since we only used it to do a test. Then, we can grab the `currentCount` value inside of the `CountDisplay` component and replace it on the paragraph that shows the count. This is what you will have:

```javascript
import React from "react";
import ReactDOM from "react-dom";

const CountDisplay = (props) => {
  return <p>The count is { props.currentCount }</p>;
};

export default CountDisplay;
```

Now you must be asking yourself how this helps us, since we just changed the place where we define the current count manually. Well, now we will talk about `state`.

<h2>State</h2>

`State`, just like props, is data to be used by a component. Again, it can be a string, a number, an object. The difference with the state is that it is private for the component and entirely controlled by it. For we to make use of the `state`, we need to learn the second way to create a component, which is through class. So, we will build class components, instead of the function components that we were building until now. To create a class component, we need to extend the `React.Component` class. Converting our `App.js` functional component to a class component, it will be like this:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import CountDisplay from "./CountDisplay";

class App extends React.Component {
  render() {
    return (
      <CountDisplay 
        currentCount={3}
      />
    );
  }
}

export default App;
```

Now, to define the `state` for this component, we must define a `constructor` for this class, and inside of it, use `this.state` to define an object that will have the initial values for the state:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import CountDisplay from "./CountDisplay";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {currentCount: 1};
  }

  render() {
    return (
      <CountDisplay 
        currentCount={3}
      />
    );
  }
}

export default App;
```

I defined the current count to 1 in the state, but notice that we are still passing the fixed value 3 to the component, and so, nothing changes for now. To use the value that is saved in the `state`, all we need to do is get it with `this.state`. With this step, the code is as follows:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import CountDisplay from "./CountDisplay";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {currentCount: 1};
  }

  render() {
    return (
      <CountDisplay 
        currentCount={this.state.currentCount}
      />
    );
  }
}

export default App;
```

Now, let's understand how we manipulate the `state` First, let's create two buttons, one to increment and another one to decrement. Let's use the `button` element, and your `App.js` file will be like this:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import CountDisplay from "./CountDisplay";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {currentCount: 1};
  }

  render() {
    return (
      <div>
        <button>
          +
        </button>
        <button>
          -
        </button>
        <CountDisplay 
          currentCount={this.state.currentCount}
        />
      </div>
    );
  }
}

export default App;
```

Now, there is an attribute on the `button` element called `onClick`. With this attribute, we can define what happens when a button is clicked. Let's use this attribute to run a function that will update our `state`, increasing or decreasing the value by 1 depending on the button pressed. First, let's create the class methods to increment and decrement, and then, assign these methods to each button accordingly. To update the state for this component, we use `this.setState`, where `this` refers to the component instance We pass to this method an object with the key that we want to change and the new value. In this case, we will use the current count, plus or minus one:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import CountDisplay from "./CountDisplay";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {currentCount: 1};
  }

  handleIncrement(event) {
    this.setState({currentCount: this.state.currentCount + 1});
  }

  handleDecrement(event) {
    this.setState({currentCount: this.state.currentCount - 1});
  }

  render() {
    return (
      <div>
        <button onClick={this.handleIncrement.bind(this)}>
          +
        </button>
        <button onClick={this.handleDecrement.bind(this)}>
          -
        </button>
        <CountDisplay 
          currentCount={this.state.currentCount}
        />
      </div>
    );
  }
}

export default App;
```

Notice that, besides putting the function in there, we added `bind(this)`. This is required so that we can use `this` inside the function. If we don't do that, `this` will be `undefined` inside of the function and `setState` won't work. There are at least 2 other ways to do this. The first one is to do the `bind` inside of the `constructor`. This is the result:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import CountDisplay from "./CountDisplay";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {currentCount: 1};

    this.handleIncrement = this.handleIncrement.bind(this);
    this.handleDecrement = this.handleDecrement.bind(this);
  }

  handleIncrement(event) {
    this.setState({currentCount: this.state.currentCount + 1});
  }

  handleDecrement(event) {
    this.setState({currentCount: this.state.currentCount - 1});
  }

  render() {
    return (
      <div>
        <button onClick={this.handleIncrement}>
          +
        </button>
        <button onClick={this.handleDecrement}>
          -
        </button>
        <CountDisplay 
          currentCount={this.state.currentCount}
        />
      </div>
    );
  }
}

export default App;
```

And there is still another way, arrow functions. If you use arrow functions, you don't have to `bind`, since arrow functions already do that automatically. Like this:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import CountDisplay from "./CountDisplay";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {currentCount: 1};
  }

  handleIncrement(event) {
    this.setState({currentCount: this.state.currentCount + 1});
  }

  handleDecrement(event) {
    this.setState({currentCount: this.state.currentCount - 1});
  }

  render() {
    return (
      <div>
        <button onClick={() => this.handleIncrement()}>
          +
        </button>
        <button onClick={() => this.handleDecrement()}>
          -
        </button>
        <CountDisplay 
          currentCount={this.state.currentCount}
        />
      </div>
    );
  }
}

export default App;
```

All of those ways to bind work, so, feel free to use the one you prefer.

Now our component is working. You can increment and decrement the count using the buttons. But we can refactor a little bit. The idea is for the buttons to be part of their own component. Let's see how we can structure our application to update the state of a component when a function is called on another component.

First, let's create a `CounterButtons.js` component. Now, let's extract whatever is in the `App.js` component and pass it to the new component we created. Our `CounterButtons.js` component will then look like this:

```javascript
import React from "react";
import ReactDOM from "react-dom";

class CounterButtons extends React.Component {
  render() {
    return (
      <div>
        <button onClick={() => this.handleIncrement()}>
          +
        </button>
        <button onClick={() => this.handleDecrement()}>
          -
        </button>
      </div>
    );
  }
}

export default CounterButtons;
```

And in our `App.js` component, we will have the following code:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import CountDisplay from "./CountDisplay";
import CounterButtons from "./CounterButtons";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {currentCount: 1};
  }

  handleIncrement(event) {
    this.setState({currentCount: this.state.currentCount + 1});
  }

  handleDecrement(event) {
    this.setState({currentCount: this.state.currentCount - 1});
  }

  render() {
    return (
      <div>
        <CounterButtons />
        <CountDisplay 
          currentCount={this.state.currentCount}
        />
      </div>
    );
  }
}

export default App;
```

If you go to your browser now and refresh, your application will be rendered, but the buttons will not work, as they don't have access to the methods that update the `state`. What we are going to do is pass functions as `props`, and call these functions in the new component we created. Let's do this.

First, in the `App.js` component, let's pass the methods through the `props` of the `CounterButton` component. Let's use `onIncrement` and `onDecrement` as names for the `props` The `App.js` component will be like this:

```javascript
import React from "react";
import ReactDOM from "react-dom";

import CountDisplay from "./CountDisplay";
import CounterButtons from "./CounterButtons";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {currentCount: 1};
  }

  handleIncrement() {
    this.setState({currentCount: this.state.currentCount + 1});
  }

  handleDecrement() {
    this.setState({currentCount: this.state.currentCount - 1});
  }

  render() {
    return (
      <div>
        <CounterButtons
          onIncrement={this.handleIncrement.bind(this)}
          onDecrement={this.handleDecrement.bind(this)}
        />
        <CountDisplay 
          currentCount={this.state.currentCount}
        />
      </div>
    );
  }
}

export default App;
```

And now, on the `CounterButtons.js` file, we change the `onClick` attribute on the buttons to call the functions passed through the `props`. To avoid having to `bind`, I will use arrow functions, so that we can call the functions directly on the `onClick` definition. This is how the `CounterButtons.js` component will be:

```javascript
import React from "react";
import ReactDOM from "react-dom";

class CounterButtons extends React.Component {
  render() {
    return (
      <div>
        <button onClick={() => this.props.onIncrement()}>
          +
        </button>
        <button onClick={() => this.props.onDecrement()}>
          -
        </button>
      </div>
    );
  }
}

export default CounterButtons;
```

In this case, where our application is really simple, this seems like adding unnecessary complexity, but in bigger and more complex applications, the separation of concepts and the organization in well defined components is vital.

<h2>Conclusion</h2>

To summarize what we saw in this post:

<ul>
    <li>There are two ways to create components, functional components and class components</li>
    <li>Props are data passed to a component to be used by them</li>
    <li>State is data that is private to a component and entirely controller by it</li>
    <li>Only class components can use state in React</li>
    <li>Besides passing values through props, you can also pass functions</li>
</ul>

With this post, I hope that I was able to explain the main concepts about components, props and state in React. Any questions, just leave it in the comments.

Cheers