Create a text typing effect with React
The typing animation effect is a very popular effect on the web. It can be used to create a chat, a loading animation, or just to add a bit of dynamism to your website.
Since OpenAI has released ChatGPT (already almost a year!), we can see this effect more than ever.
For a project, I had to create a similar effect, and I thought it would be a good idea to share it with you.
The effect
The code
For this effect, we will use a custom hook:
const useTypingEffect = (
const [currentPosition, setCurrentPosition] = useState(0);
const items = isTypeByLetter ? text.split("") : text.split(" ");
if (currentPosition >= items.length) return;
const intervalId = setInterval(() => {
setCurrentPosition((prevPosition) => prevPosition + 1);
clearInterval(intervalId);
}, [currentPosition, items, duration]);
return items.slice(0, currentPosition).join(isTypeByLetter ? "" : " ");
We have 3 parameters: the text to display, the duration between each letter/word, and a boolean to know if we want to type by letter or by word (I use this in the next section).
In our example below we use the hook like with a texts
array, and we change the text every 5 seconds, like this:
import useTypingEffect from "./useTypingEffect";
"This is a simple text typing effect in React",
"This effect is created using React Hooks",
"We can use this effect to create a typing effect for our portfolio",
"We can also use this effect to create a typing effect for our resume",
"or for your landing page",
type TextTypingEffectProps = {
isTypeByLetter?: boolean;
export const TextTypingEffectWithTexts: React.FC<TextTypingEffectProps> = ({
const [textIndex, setTextIndex] = React.useState(0);
const textToShow = useTypingEffect(
const intervalId = setInterval(() => {
setTextIndex((prevIndex) =>
prevIndex >= texts.length - 1 ? 0 : prevIndex + 1
clearInterval(intervalId);
<span className="text-black dark:text-white" key={textIndex}>
More
This is very simple hook, we can improve it a bit in term of animation.
For example, we can take inspiration from chat.openai, and add a fade out effect and a cursor.
const TIME_TO_FADE = 300;
const TIME_INTERVAL = 3000;
const TIME_PER_LETTER = 100;
export const TextTypingEffectWithTextsFadeOut = () => {
const [textIndex, setTextIndex] = React.useState(0);
const [fadeText, setFadeText] = React.useState(true);
const [fadeCircle, setFadeCircle] = React.useState(true);
const textToShow = useTypingEffect(texts[textIndex], TIME_PER_LETTER, false);
const timeToTypeText = texts[textIndex].split(" ").length * TIME_PER_LETTER;
const circleTimeout = setTimeout(() => {
}, timeToTypeText + 1000);
const textTimeout = setTimeout(() => {
setTextIndex((prevIndex) =>
prevIndex >= texts.length - 1 ? 0 : prevIndex + 1
clearTimeout(circleTimeout);
clearTimeout(textTimeout);
className={`inline-flex items-center text-black duration-300 dark:text-white ${
fadeText ? "opacity-1 translate-y-0" : "translate-y-2 opacity-0"
className={`ml-2 h-3 w-3 rounded-full bg-black duration-300 dark:bg-white ${
fadeCircle ? "" : "h-0 w-0 opacity-0"
Published: 9/12/2023
Join my newsletter to stay updated about the latest things I've created and discover the great finds I've come across on the internet.