Skip to content

M03 - Built-in React Hooks

Introduction

Hooks let you use different React features from your components. You can either use the built-in Hooks or combine them to build your own. Hooks are functions that let you “hook into” React state and lifecycle features from function components. Hooks don’t work inside classes. They are heavily used in a function based React application development.

Note

Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function. By following this rule, you ensure that Hooks are called in the same order each time a component renders.

State Hooks

To start working with a state hook, you need to import useState or useReducer to your React app. State lets a component remember information what it have. For example, a form component can use state to store the input value, while an image gallery component can use state to store the selected image index.

To add state to a component, use one of these Hooks:

  • useState declares a state variable that you can update directly.
  • useReducer declares a state variable with the update logic inside a reducer function.

You will need to import those before you can use them.

1
import React, { useState, useReducer } from 'react';

useState

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

A few examples how to initialize a state are visible below.

1
2
3
const [age, setAge] = useState(42);
const [name, setName] = useState('Kirsi Kernel');
const [todos, setTodos] = useState([{ text: 'Learn React Hooks!' }]);

You can modify state to call defined hook function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
export default function App() {
  const [age, setAge] = useState(42);

  return (
    <>
      <button onClick={() => setAge(age + 1)}>
        Increment age
      </button>
    </>
  );
}

Look more useState examples from here : useState

useReducer

useReducer is a React Hook that gives us more control over state management than useState, making it easier to manage complex states. Its basic structure is:

1
const [state, dispatch] = useReducer(reducer, initialState)

The reducer function is a pure function that accepts state and action as parameters and returns an updated state. Look at its structure below.

1
2
3
4
const reducer = (state, action) => {
  // logic to update state with value from action
  return updatedState
}

The action parameter helps us define how to change our state. It can be a single value or an object with a label (type) and some data to update the state (payload). It gets its data from useReducer's dispatch function. Reducer will use conditionals (typically a switch statement) to determine what code to execute based on the type of action (action.type).

Counter example:

ShoppingList example:

Look more useReducer examples from here : useReducer

Ref Hooks

When you want a component to remember some information, but you don’t want that information to trigger new renders, you can use a ref.

You need to add a ref to your component by importing the useRef Hook from React:

1
import { useRef } from 'react';

Inside your component, call the useRef Hook and pass the initial value that you want to reference as the only argument.

1
const ref = useRef('Kirsi Kernel');

useRef returns an object like this:

1
2
3
{ 
  current: 'Kirsi Kernel' // The value you passed to useRef
}

You can access the current value of that ref through the ref.current property. This value is intentionally mutable, meaning you can both read and write to it.

In a below example component will hold button clicked times in ref.current but it is not rendered in the UI.

Note

Note that the component doesn’t re-render with every ref.current change. Like state, refs are retained by React between re-renders. However, setting state re-renders a component. Changing a ref does not!

Effect Hook

Effect hook can be used for example data fetching, subscriptions, or manually changing the DOM from functions. It serves the same purpose as componentDidMount, componentDidUpdate and componentWillUnmount in React classes.

To start working with a state hook, you need to import useEffect to your React app.

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

A below example sets the document title after React updates the DOM.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Code here will run after *every* render by default
    document.title = `You clicked ${count} times`;
  });

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

When your app call useEffect, you’re telling React to run your effect function after flushing changes to the DOM. Effects are declared inside the function component so they have access to its props and state. By default, React runs the effects after every render, including the first one.

Sometimes you don't want to effect run in every render time. You can tell React to skip applying an effect if certain values haven’t changed between re-renders. To do so, pass an array as an optional second argument to useEffect:

1
2
3
useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // Only re-run the effect if count changes

If you want to run an effect and clean it up only once, you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This is very usefull for example if you want to load data from the server side when the application is launching.

1
2
3
4
useEffect(() => {
  // load data from server side
  // store loaded date to states
}, []); 

You need to call return if you want to clear something what has happend with a useEffect. In a below example, a timer interval will be cleared after a component is removed from the screen.

Note

We will use useEffect later when we are loading an external data to our React application.

Performance Hooks

Look more information from here: Performance Hooks

Context Hooks

This will be cover later in material X.

Read more