Create a delayed component
Tags: react, javascript, tutorial
Published: 2022-09-24 00:25:35

Today we are going to learn why I needed to create such component and how I went about doing it with [setTimeout()](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) and understanding why Reacts render method works in a synchronous way and how the hooks API can be used to create a delayed list effect.

So if you try and do what is in the code example below in React it won't work and render method will wait for setTimeout() to complete by which time all your components will appear in one go and you can't add fancy animation (a list item in this case).

``` javascript
const todos = [
  {
    name: 'Learn how to create a delayed component',
    isComplete: false
  },
  {
    name: 'Like this post',
    isComplete: false
  },
  {
    name: 'Share this post (see what I am getting at here) 😀',
    isComplete: false
  }
];
```
..and our Todos component (the wrong way):

``` javascript
import React from 'react';

export default TodoList = () => {
  return (
    <ul>
      {todos.map(({ name, isComplete }, index) =>
        setTimeout(() => {
          <li key={index} className={`${isComplete ? 'isComplete' : ''}`}>
            {name}
          </li>;
        }, index * 200)
      )}
    </ul>
  );
};
```

Now the `<TodoList />` component may or may not do what you think it would. Reacts render process is synchronous meaning when `setTimeout()` is called it will wait until the timer function has finished then render the elements so you will get no delay when each list item renders.

Let's try that again, but first, we need to create our `<DelayedComponent/>`

``` javascript
import React from 'react';

export default DelayedComponent = ({ wait, children }) => {
  const [isShown, setIsShown] = React.useState(false);
  
  React.useEffect(() => {
    
    const timer = setTimeout(() => {
      setIsShown(true);
    }, wait);
    
    return () => clearTimeout(timer);
  }, [wait]);
  
  return isShown && children;
};
```

Let's walk through how this works. We need to declare two props I have named them `wait` this accepts the amount of time the component should wait until it should be rendered and the other is a standard prop name which is always called `children` and allows you to render any child elements nested within `<DelayedComponent/>` i.e:

``` javascript
<DelayedComponent>
  {/* start child elements */}
  <h1>This is a title</h1>
  <div>This is the main content</div>
  {/* end child elements */}
</DelayedComponent>
```

Then we declare the state for showing the intended element/child. For this, we can make use of the [`useState()`](https://reactjs.org/docs/hooks-state.html) hook. We can set the initial value of this to `false`.

Now, things get a little interesting as we start to use [`useEffect()`](https://reactjs.org/docs/hooks-effect.html) hook which can be really powerful when implemented correctly. `useEffect()` is essentially the `componentDidMount()` lifecycle method we get on class-based components and when you `return` inside the `useEffect()` hook that is also similar as `componentWillUnmount()` we again have on class-based components.

So what we have done is assigned the variable `timer` to the `setTimeout()` function and passed in the `wait` prop to the millisecond's parameter for the timer function.

``` javascript
React.useEffect(() => {
  const timer = setTimeout(() => {
    setIsShown(true);
  }, wait);

  return () => clearTimeout(timer);
}, [wait]);
```

If you look at the final argument of the `useEffect()` hook you will see we also pass in an array. This is the dependency array and what this does is keeps track of anything we pass in so in our case it would be the `wait` prop. Finally we clean up the timer function by clearing it with `clearTimeout()`