Creating an animated typing effect in React
Tags: react, texttypinganimation
Published: 2022-09-11 18:32:54

---
title: Creating an animated typing effect in React
published: true
description: How to create a text typing animation effect in react in simple steps.
tags: reactjs, texttypinganimation
# cover_image: https://barcelonacodeschool.com/files/pics/text-type-animation-effect-react.gif
# Use a ratio of 100:42 for best results.
---

<img src='https://barcelonacodeschool.com/files/pics/text-type-animation-effect-react.gif' alt='A layout component to create a typewriter typing animation effect for text'/>

The idea behind this is that we render text from the state and keep updating state variable one character at a time with a bit of delay. 

Each time state is updated our component will re-render showing text "typed" one character after another. 

So first thing in our React app we will create a component. Let's name it `TextTyper`. We will need to have `useState` and `useEffect` hooks in it, so we can import them right away:

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

const TextTyper=() => {
  const [typedText, setTypedText] = useState("");

  return <span>{typedText}</span>
}

export default TextTyper
```

In state we have declared a variable `typedText` which is rendered inside `span` HTML element. This would be the variable which we are going to update. 

Let's say we want to print "Banana". First we will render empty string, then we will add "B" to `typedText` and see it in the page, then we will update it to "Ba", and so on...

Let's create  a function `typingRender`. It will take 3 arguments: the whole phrase to type, the updater method which will be our `setTypedText` and an interval value to tell the function the delay between rendering each character.

In this function we will use variable `localTypingIndex` to go through the indexes of characters in the incoming string and take them one by one. We will also declare a variable `localTyping` to mirror what should be in state and add letters to it to put to state:

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

const TextTyper=() => {
  const [typedText, setTypedText] = useState("");

  const typingRender = (text, updater, interval) => {
// local counter used to go through indexes of the phrase
    let localTypingIndex = 0;
// local string to add characters to and put to state
    let localTyping = "";
    if (text) {
// if we have a phrase to type we will start the interval
      let printer = setInterval(() => {
// if our local index counter is less than the length of the phrase we keep going
        if (localTypingIndex < text.length) {
// we set to state our local string with the phrase
          updater((localTyping += text[localTypingIndex]));
// and increase the local index
          localTypingIndex += 1;
        } else {
// once we reached the end of the phrase we reset local index
          localTypingIndex = 0;
// clear local string with phrase
          localTyping = "";
// clear the interval to stop
          clearInterval(printer);
        }
      }, interval);
    }
  };

  return <span>{typedText}</span>
}

export default TextTyper
```

Now we have our typing function it's time to execute it. We want this to happen once when component is initially rendered so we will use `useEffect` with empty array of dependencies:

```js
const TextTyper=() => {
  const [typedText, setTypedText] = useState("");
// declare the variable to hold the phrase
const text = 'This will be the phrase printed one by one character'
// declare a variable with the interval of 100 milliseconds
const interval = 100
  const typingRender = (text, updater, interval) => {
    let localTypingIndex = 0;
    let localTyping = "";
    if (text) {
      let printer = setInterval(() => {
        if (localTypingIndex < text.length) {
          updater((localTyping += text[localTypingIndex]));
          localTypingIndex += 1;
        } else {
          localTypingIndex = 0;
          localTyping = "";
          clearInterval(printer);
        }
      }, interval);
    }
  };
// run this effect on first render
  useEffect(() => {
// call the function passing a phrase, setter method for state and interval var
    typingRender(text, setTypedText, interval);
  }, [text, interval]);

  return <span>{typedText}</span>
}

export default TextTyper
```

Now the component will work perfectly fine but we can make it more flexible, so all the data for it to work will come via props and we will even set the variable to control inside which HTML element we want to render our phrase:

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

const TextTyper=({
// now the phrase, interval and HTML element desired will come via props and we have some default values here
  text = "",
  interval = 100,
  Markup = "span"
}) => {
  const [typedText, setTypedText] = useState("");

  const typingRender = (text, updater, interval) => {
    let localTypingIndex = 0;
    let localTyping = "";
    if (text) {
      let printer = setInterval(() => {
        if (localTypingIndex < text.length) {
          updater((localTyping += text[localTypingIndex]));
          localTypingIndex += 1;
        } else {
          localTypingIndex = 0;
          localTyping = "";
          clearInterval(printer);
        }
      }, interval);
    }
  };
  useEffect(() => {
    typingRender(text, setTypedText, interval);
  }, [text, interval]);

  return <Markup>{typedText}</Markup>
}

export default TextTyper
```

So now if we want to use this we can import the component and render it with passing some props:

```js
// importing our component in App.js
import TextTyper from './TextTyper'

function App() {
const textToRender = 'This will be the phrase printed one by one character'
  return (
    <div className="App">
 {/* rendering it passing */}
    <TextTyper text={textToRender} interval={10} Markup={"code"} />
    </div>
    );
}

export default App;
```

Here is a link to the working code [sandbox](https://codesandbox.io/s/text-type-animation-effect-react-6o7j0d). 

You can also [install and import this component](https://www.npmjs.com/package/text-type-animation-effect-react) with `npm` or `yarn`