Skip to content

M02 - Components

Introduction

Components are independent and reusable bits of code. They serve the same purpose as JavaScript functions, but work in isolation and returns HTML via a render function. React apps are made out of components. A component is a piece of the UI (user interface) that has its own logic and appearance. A component can be as small as a button, or as large as an entire page.

Tip

Components are one of the core concepts of React.

You can use an ES6 class to define a component. When creating a React component, the component's name must start with an upper case letter. The component has to include the extends React.Component statement, this statement creates an inheritance to React Component, and gives your component access to React Component's functions. The component also requires a render() method, this method returns HTML.

1
2
3
4
5
class Movie extends React.Component {
  render() {
    return <h1>Terminator: 1984</h1>
  }
}

A function and const based components also returns HTML, and behaves pretty much the same way as a Class based component. They are a newer way to define a component in react applications.

The simplest way to define a component is to write a JavaScript function:

1
2
3
function Movie() {
  return <h1>Terminator: 1984</h1>
}
1
2
3
const Movie = () => {
  return <h1>Terminator: 1984</h1>
}

Note

We will focus function and const based components in this course!

Render component to HTML

React renders HTML (or components) to the web page by using a function called ReactDOM.render(). You will need to find HTML target and use ReactDOM.createRoot() function to create a React root for the supplied container and return the root. The root can be used to render a React element into the DOM with render.

html
1
2
3
<body>
  <div id="root"></div>
</body>

You can use above Movie component in render() function:

JavaScript
1
2
3
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
root.render(<Movie/>);

Nesting components

Remember that react components are JavaScript functions that return a markup.

1
2
3
function Movie() {
  return <h1>Terminator: 1984</h1>
}

Now that you’ve declared Movie, you can nest it into another component.

1
2
3
4
5
6
7
8
function Movies() {
  return (
    <>
      <h1>My movies</h1>
      <Movie/>
    </>
  );
}

Note

Notice that <Movie /> starts with a capital letter. That’s how you know it’s a React component. React component names must always start with a capital letter, while HTML tags must be lowercase.

Component properties

Function is a valid React component and it accepts a single props (which stands for properties) object argument with data and returns a React element. In React applications, props are passed to components via attributes. Your own components can also use props. This lets you make a single component that is used different places in your app, with slightly different properties in each place. Props might remind you of HTML attributes, but you can pass any JavaScript value through them, including objects, arrays, and functions.

Note

Remember that props are set by the parent and they are fixed throughout the lifetime of a component.

Component state - Updating the screen

You will need to use component state for a data that is going to be changed and updated to the screen. Use React Hooks to get state working inside a function or const based components.

Example: ClickCounter

In a below example line 2 count state variable will be initialized with zero value and it can be modified calling setCount function.

First, import useState from React:

1
import { useState } from 'react';

Now you can declare a state variable inside your component. You’ll get two things from useState: the current state count, and the function that lets you update it setCount. You can give them any names, but the convention is to write [something, setSomething].

Declared buttonClicked function will be called when a button is clicked. count value will be increased with setCount() function. This time, count will be 1. Then it will be 2. And so on. Defined setCount() is React Hooks function and it will cause the component updated and rendered again. Only a modified content will be rendered to browsers DOM.

Functions starting with use are called Hooks. useState is a built-in Hook provided by React. You can find other built-in Hooks in the API reference. You can also write your own Hooks by combining the existing ones.

Note

If you are using and rendering the same component multiple times, each will hat it's own state.

Handling Events

Handling events with React elements is very similar to handling events on DOM elements with JavaScript. Remember that, React events are named using camelCase, rather than lowercase and with JSX you pass a function as the event handler, rather than a string.

HTML

1
2
3
<button onclick="buttonClicked()">
  Click Me!
</button>

React

1
2
3
<button onClick={buttonClicked}>
  Click Me!
</button>

Define a event handling function inside your component with function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function MyButton() {

  function handleClick() {
    alert('You clicked me!');
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  );
}

Usually event handling function is declared inside a component with a const based array function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function MyButton() {

  const handleClick = () => {
    alert('You clicked me!');
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  );
}

Note

Notice how onClick={handleClick} has no parentheses at the end! Do not call the event handler function: you only need to pass it down. React will call your event handler when the user clicks the button.

A common thing in React is how to pass a value as a parameter through the onClick event handler. In order to pass a value as a parameter through the onClick handler use an arrow function, which returns a call to the handleClick function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function MyButton() {

  const handleClick = (name) => {
    alert(`Hello, ${name}!`);
  }

  return (
    <button onClick={() => handleClick('Kirsi Kernel')}>
      Click me
    </button>
  );
}

Let's look an another example, which will send a button's value to event handling function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function MyComponent() { 

  const changeColor = (color) => {
    alert(color);
  }

  return (
    <>
      <button value="blue" onClick={ (e) => changeColor(e.target.value)}>Color Change - Blue</button>
      <button value="yellow" onClick={ (e) => changeColor(e.target.value)}>Color Change - Yellow</button>
    </>
  );
}

Export the component

The export default prefix is a standard JavaScript syntax (not specific to React). It lets you mark the main function in a file so that you can later import it from other files.

Person.js
1
2
3
4
5
6
7
8
export default function Person() {
  return (
    <img
      src="https://randomuser.me/api/portraits/women/31.jpg"
      alt="Kirsi Kernel"
    />
  )
}

Use Person in App.js:

App.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import Person from "./Person";

export default function App() {
  return (
    <>
      <h1>Persons</h1>
      <Person/>
    </>
  );
}

You can't have multiple default imports. You will need to use named exports, if you need to have multiple exports from same file.

Person.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
export default function Person() {
  return (
    <img
      src="https://randomuser.me/api/portraits/women/31.jpg"
      alt="Kirsi Kernel"
    />
  )
}

export function Profile() {
  return (
    <h1>Profile</h1>
  )
}

Use Person and Profile in App.js:

App.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import Person, { Profile } from "./Person";

export default function App() {
  return (
    <>
      <h1>Persons</h1>
      <Person/>
      <Profile/>
    </>
  );
}

And a little bit bigger example in CodeSandBox. You can use Person to show only an image (for example multiple Persons - list of images) and use Profile if needed.

Tip

The magic of components lies in their reusability: you can create components that are composed of other components. But as you nest more and more components, it often makes sense to start splitting them into different files. This lets you keep your files easy to scan and reuse components in more places.

Read more