React Render Lifecycle and useEffect Hook
Tags: react, hooks, functional, javascript
Published: 2023-05-20 20:23:22

First of all, I want to state the obvious: React Class Components are dead 💀

This post is about how the react render lifecycle works on **functional** components.

## Functional Components
Components are functions that must return a `JSX.Element`, which means HTML tags with some JS sugar.

You can declare and export a React functional component by declaring and exporting a function. 

Assuming you're familiar with `useState`, let's look at an example:

```jsx
import React, { useState } from "react"

export const Counter = () => {
  const [counterValue, setCounterValue] = useState(0)
  const increaseValue = () => {
    setCounterValue(counterValue + 1)
  }

  return (
    <button id="value-button" onClick={increaseValue}>
      { counterValue }
    </button>
  )
}
```

You can declare a functional component using the function keyword as well:

``` react
export function Counter() {
  const [counterValue, setCounterValue] = useState(0)
  const increaseValue = () => {
    setCounterValue(counterValue + 1)
  }

  return (
    <button id="value-button" onClick={increaseValue}>
      { counterValue }
    </button>
  )
}
```


## The Render process
Whenever a state or prop of the component changes, the function's code will run again.

This means that each click on the 'value-button' will:

- Increase counterValue.
- Redeclare increaseValue, creating a new memory reference.
- Execute the return block.


## The React useEffect Hook
Suppose you want to perform an action, like showing an alert, every time a component is rendered.

You can use the useEffect hook to add side effects to your component. It has 3 different configurations: **[someStateValue]**, **[]**, and **no dependencies**.

Here's a simple example that triggers an alert whenever the component renders:

``` react
import React, { useEffect, useState } from "react"

export const Counter = () => {
  const [counterValue, setCounterValue] = useState(0)
  const increaseValue = () => {
    setCounterValue(counterValue + 1)
  }

  useEffect(() => {
    alert('I run whenever the component renders')
  }) 

  return (
    <button id="value-button" onClick={increaseValue}>
      { counterValue }
    </button>
  )
}
```

In JavaScript's single-threaded environment, the Event Loop handles tasks like `useEffect`. The `useEffect` task is added to a task queue. 

After the browser finishes painting the screen updates (the render), the **Event Loop** runs the queued tasks. 

This doesn't block the rendering process.

## Empty Array []
If an alert on EVERY state change sounds annoying, you can add a second parameter to `useEffect`, an empty array []. 

This ensures that the effect runs only once after the component's initial render:

``` react
useEffect(() => {
  alert('I run once, after the component is first rendered')
}, [])
```

## Specific Dependencies
For specific side effects linked to one or more states, you can add them to the dependencies array. 

`useEffect` will then execute whenever any of those states change:

``` react
useEffect(() => {
  alert('I run whenever counterValue changes.')
}, [counterValue])
```

Remember, it's a good practice to include only the states used in the dependencies array. 

Be mindful of the "no dependencies" scenario, as it could lead to unnecessary effect runs and performance issues.

Stay tuned for more on React rendering, where we'll delve into `useCallback` and `useMemo` hooks in future posts!