Skip to content

Typing Effect

Type a sentence one character at a time with a blinking cursor, using a timer that cleans up after itself.

Stage 4intro2 min read

Problem Statement

Build a TypingEffect component that types out a given text one character at a time, deletes it, and repeats forever.

Functional Requirements

  1. Props: Take a text string and a delay in milliseconds between steps.
  2. Type: Start from an empty string and add one character per tick until the full text shows.
  3. Delete and loop: Once the full text shows, remove one character per tick back to empty, then start typing again.
  4. Cursor: Show a | cursor after the text that blinks with a CSS animation.

Technical Constraints

  • Use one setInterval and clear it in the useEffect cleanup.
  • Keep the typing position and direction in a useRef, so they do not cause extra renders.

Code Breakdown

1. CSS Animation (styles.css)

span {
  animation: hideAndShow 1s infinite;
}

@keyframes hideAndShow {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

Explanation:

  • Creates a blinking cursor effect for the <span> element
  • hideAndShow animation toggles opacity between 0 and 1 every second
  • infinite makes the animation loop continuously

2. App Component (App.js)

import React from "react";
import TypingEffect from "./components/TypingEffect";

const App = () => {
  return (
    <div>
      <TypingEffect text="I'm a FullStack Developer" delay="100" />
    </div>
  );
};

Explanation:

  • Main component that renders the TypingEffect component
  • Passes two props:
    • text: The string to be typed
    • delay: Time (ms) between each character addition/removal

3. TypingEffect Component (TypingEffect.js)

import { useEffect, useRef, useState } from "react";

const TypingEffect = ({ text, delay }) => {
  const [displayText, setDisplayText] = useState("");
  const velocityRef = useRef({ speed: 1, endIndex: 0 });

  useEffect(() => {
    const intervalId = setInterval(() => {
      if (velocityRef.current.endIndex >= text.length) {
        velocityRef.current.speed = -1; // Switch to deleting mode
      } else if (velocityRef.current.endIndex === 0) {
        velocityRef.current.speed = 1; // Switch to typing mode
      }
      velocityRef.current.endIndex += velocityRef.current.speed;
      setDisplayText(text.slice(0, velocityRef.current.endIndex));
    }, delay);

    return () => clearInterval(intervalId);
  }, [delay, text]);

  return (
    <div>
      {displayText}
      <span className="">|</span>
    </div>
  );
};

JavaScript/React Concepts Used

1. React Hooks

  • useState: Manages the currently displayed text
  • useEffect: Handles the side effect of typing animation
  • useRef: Stores mutable values that persist across renders without causing re-renders

2. Key Methods

  • setInterval: Repeatedly executes the typing/deleting logic at specified intervals
  • clearInterval: Cleans up the interval when component unmounts
  • Array.slice: Extracts portion of the text to display

3. Why useRef?

  • We need to track speed and endIndex between renders
  • Changing these values shouldn't trigger re-renders
  • Regular variables would reset on each render

Code Flow

  1. Initialization:

    • Component mounts with displayText initialized to an empty string
    • velocityRef initialized with speed: 1 (typing) and endIndex: 0
  2. useEffect Execution:

    • Sets up an interval that runs every delay milliseconds
    • Each interval tick:
      • Checks if we've reached text end (switch to deleting)
      • Checks if we're back at start (switch to typing)
      • Updates endIndex based on current speed
      • Updates displayText with appropriate slice of text
  3. Rendering:

    • Shows current displayText with blinking cursor (|)

DRY Run Example

Let's simulate with text="Hi" and delay=100ms:

Time (ms)endIndexspeeddisplayTextAction
001""Initialize
10011"H"Add first character
20021"Hi"Add second character
3002-1"Hi"Hit length, reverse
4001-1"H"Remove last char
5000-1""Back to start
60001""Hit start, reverse
70011"H"Cycle repeats...

This creates an infinite typing/deleting loop for the text "Hi".

In this topic

Done with this topic?

How well do you know it?

PreviousNested Checkboxes