Skip to content

How to code in React

veerleprins edited this page Dec 30, 2020 · 5 revisions

Based on the pros and cons of the different frameworks that I have mentioned on this page, I decided to start using React. But to use React, it is important to know how React is constructed and which code can be used.

Jump to:

What is React?

React is a library based on components. According to freecodecamp components are independent, reusable pieces of code that can divide the User Interface into smaller parts. These 'smaller parts' are for example paragraphs, articles, buttons or headings.

How to write components?

Within React we can code a component in two ways: Using functional components (also known as Stateless components) or class components (also known as Stateful components). Both types of components do have a number of points that correspond. For example, both include:

  • A name of the component with a capital letter.
  • Curly braces in which the code is written.
  • Props (this is the abbreviation for properties) that are included.

But the way we tell React which one to use differs. But before we can look at the code structure of these specific components, it is important to know what JSX is.

JSX

JSX stands for JavaScript XML and looks like a combination of JavaScript and HTML (Source, Source) :

const paragraph = <p> Hello there, this is JSX! </p>;
const button = <button> This is a button. </button>;

We use JSX to create the elements on the User Interface and inject javascript values so that our components can become dynamic. Although JSX does not necessarily have to be used within React, I will work with it myself and will also use it in the examples below. JSX also ensures that you no longer have to worry about loose JavaScript and HTML files.

Class components

The structure of a class component starts with indicating to React that it is a class component. We do this by putting the keyword 'class' before the name of the component. We also put 'extends React.Component' between the name of the component and the curly braces:

class App extends React.Component {
  render () { 
    return <h1>This is the title of the page!</h1>;
  }
}

We can make this class component dynamic and reusable by providing props. We do this by using the keyword 'this' followed by '.props.' and the variable name we want to display:

class App extends React.Component {
  render () { 
    return <h1>This is the title of the page! Your name is: { this.props.name }</h1>;
  }
}

(Source)

Functional components

Compared to class components, it is easier to tell React that we want to use a functional component. We do this by writing the functional component like a normal function: We do this by putting the keyword 'function' before the name of the component. Behind the name of the component there are brackets where, just like with a normal function, variables can be added:

// Old way:
function App () {
  return <h1>This is the title of the page!</h1>
}

// Or ES6 way:
const App = () => {
  return <h1>This is the title of the page!</h1>
}

We can make this functional component dynamic and reusable by providing props. We do this by adding props in the brackets:

// Old way:
function App (props) {
  return <h1>This is the title of the page! Your name is: { props.name }</h1>
}

// Or extracting the properties in ES6 way:
const App = ({ name }) => {
  return <h1>This is the title of the page! Your name is: { name }</h1>
}

What are life cycle methods?

Life cycle methods are a cycle of events that take place from the beginning of the component to the end of a component (Source). First, life cycle methods could only be used using the class components. But since React version 16.8, we can also access life cycle methods through hooks when we write functional components(Source). First I will explain how life cycle methods work within class components and then explain that hooks 'hook' into the life cycle methods within the functional components.

Life cycle methods within classes

render()

Several standard life cycle methods are known in React classes. The most important and only required life cycle method is: render(). This method ensures that all elements are rendered to the User Interface. This is also where JSX is written in the code (Source):

class Title extends React.Component {
  render {
    return (
        <h1>Welcome to the page</h1>
    )
  }
}

constructor() and state

There is also the constructor(). This method is called once when the component is started. In the constructor you use 'state' which is an object in which values from the props are stored. States can be used to make the component reusable and updating without calling it every second. We create this state object by equating this.state with an object in which values are stored (Source, Source):

class Title extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      name: "Isabelle"
    }
  }
  render {
    return (
        <h1>Welcome to the page, { this.state.name }</h1>
    )
  }
}

componentDidMount() and setState

The componentDidMount() is a life cycle method that is only called by React when all elements on the page have already been rendered for the first time correctly. This method is the perfect place to fetch APIs and call the this.setState() to pass the data to the page after fetching (Source). Below is an example of componentDidMount when we fetch the data and change the state with this.setState() (Source):

componentDidMount() {
  // Fetching the movies:
  fetch('https://some-api.com/movies')
    .then((response) => response.json())
    .then(movies => {
      // Storing the movies in the state:
      this.setState({ allMovies: movies });
    })
}

componentDidUpdate()

The componentDidUpdate() method is called for the first time when a change has taken place and the page has already been rendered. This method can also be useful when a fetch to an API has to be done again (for example with a life update of a specific dataset). It is important to write an if else condition in this because otherwise an infinite loop will be created and a re-rendering. The latter in particular ensures that the user may experience delays or a site that does not work properly (Source):

componentDidUpdate(prevState) {
  if (this.state.allMovies !== prevState.allMovies) {
    console.log('The movies state has changed.)
  }
}

componentWillUnmount()

The componentWillUnmount() method is called immediately when a component needs to be removed from the DOM. A setState in a componentWillUnmount() therefore has no reason: the component is never reloaded once it has been removed from the DOM (Source, Source):

import React from 'react'; 
class Paragraph extends React.Component {   
  render() { 
    return <p>This is a simple paragraph.</p>; 
  }

  componentWillUnmount() { 
    console.log('This component is going to be unmounted.'); 
  }  
} 
  
export default class App extends React.Component { 
  state = { shown: true }; 
  deleteText = () => { 
    this.setState({ shown: false }); 
  }; 
  
  render() { 
    let text; 
    if (this.state.shown) { 
      text = <Paragraph />; 
    } 
    return ( 
      <> 
        <h1>This is the title of the page</h1>
        {text} 
        <button onClick={this.deleteText}> 
          Delete
        </button> 
      </> 
    ); 
  } 
} 

First, the output will be ( Note: The [ ] represent a button. ):

This is the title of the page
This is a simple paragraph.
[ Delete ]

But after the button is pressed ( Note: The [ ] represent a button. ):

This is the title of the page
[ Delete ]

Hooks within functional components

As I mentioned, since version 16.8 we can use hooks within functional components. According to React's documentation, hooks are:

Functions within functional components that allow you to 'hook into' React's status and life-cycle methods..

So, we can use life cycle methods within functional components through hooks. For this reason, hooks can only be used within functional components.

Like the original life cycle methods, there are a number of fixed hooks available in React, but you can also write your own. Examples of built-in hooks are: useState() and useEffect(). I will briefly explain what useEffect() and useState() are.

States within useState()

For class components we create a state by using the keyword this inside the constructor. With hooks, on the other hand, we don't have to use this, just create a state directly in the component and store it as some sort of array:

import React, { useState } from 'react';

function Person () {
  const [age, setAge] = useState(0);
}

What is actually happening here is the following:
First, the useState hook must be imported to use states. Then we create a state using useState() and set the starting value equal to the number 0. Finally we store it in a variable, in our case that is age (but this might as well have been called count or num) and we get a function that can update the variable age. In our case, this function is called setAge.
This is similar to the this.setState() in the class clause, except that useState hook does not concatenate the old value and the new value (Source). The advantage of this variable is that it can also be used outside of the component, while normally variables disappear from a function. (Source).

And of course multiple states can also be created:

import React, { useState } from 'react';

function Person () {
  const [age, setAge] = useState(0);
  const [height, setHeight] = useState(0);
  const [color, setColor] = useState("Blue");
}

useEffect()

The useEffect() hook is actually a combination of componentDidMount(), componentDidUpdate() and componentWillUnmount() together.

With the class variant you have a componentDidMount and componentDidUpdate that in some cases can provide exactly the same code. Sometimes you want something to happen both after the first rendering and after the update. With class components, this can only be done by publishing code. Due to useEffect() in functional components, this is no longer necessary (Source):

import React, { useState, useEffect } from 'react';

const Count = () => {
  const [num, setNum] = useState(0);

  useEffect(() => {    
    console.log(`You clicked ${num} times`);  
  });

  return (
    <>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count - 1)}>
        Click me
      </button>
    </>
  );
}

In the case of this Count component, it would be nonsense to re-render the useEffect every time it is not needed. This can be solved by filling in the following:

  useEffect(() => {    
    console.log(`You clicked ${num} times`);  
  }, [num]);

By passing num as an option, we ensure that the page is only rendered again if num changes.

Clone this wiki locally