DEV Community

Cover image for Type writer Effect like ChatGPT with React
Duoc95
Duoc95

Posted on

Type writer Effect like ChatGPT with React

Creating a Typewriter Effect in React with React Markdown

In this blog post, I'll walk through how to create a typewriter effect for React applications. This effect will simulate the appearance of text being typed onto the screen in real-time. I will also integrate React Markdown to render Markdown-formatted text, adding an extra layer of functionality that allows you to include formatted text, links, tables, and more within typewriter effect.

Getting Started

First, ensure you have a React project set up. If you need to set one up, you can do so by using Vite:


npm create vite@latest my-typewriter-effect

cd my-typewriter-effect

npm install

Enter fullscreen mode Exit fullscreen mode

Next, install react-markdown and remark-gfm to render Markdown-formatted text:


npm install react-markdown remark-gfm

Enter fullscreen mode Exit fullscreen mode

Implementing the Typewriter Effect

The core of our typewriter effect is a React component named TypewriterEffect. This component takes in a text string and optionally, a typing speed and a callback function to execute once the typing animation is complete. It uses the useState and useEffect hooks to manage the state and side effects, respectively.

Here's the code for the TypewriterEffect component:


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

import CustomReactMarkdown from './components/CustomReactMarkdown';

import { processMarkdown } from './utils/questions'; // Assume this is a function you've defined to preprocess Markdown text.



const TypewriterEffect = ({

 text,

 typingSpeed = 10,

 onRenderingEnd,

}) => {

 const [visibleLength, setVisibleLength] = useState(0);

 const processedText = processMarkdown(text);

 const contentRef = useRef(null);



 useEffect(() => {

  if (visibleLength < processedText.length) {

   const timer = setTimeout(() => {

    setVisibleLength(visibleLength + 1);

   }, typingSpeed);



   return () => clearTimeout(timer);

  } else if (onRenderingEnd) {

   onRenderingEnd();

  }



 }, [visibleLength, processedText.length, typingSpeed, onRenderingEnd]);



 return (

  <div ref={contentRef}>

   <CustomReactMarkdown content={processedText.substring(0, visibleLength)} />

   {visibleLength < processedText.length && <span className="typing-indicator" />}

  </div>

 );

};

Enter fullscreen mode Exit fullscreen mode

CustomReactMarkdown Component

The CustomReactMarkdown component is a simple wrapper around the ReactMarkdown component that configures it to use the remark-gfm plugin, enabling GitHub Flavored Markdown, and sets up custom rendering for table elements to enhance their appearance.


import ReactMarkdown from 'react-markdown';

import remarkGfm from 'remark-gfm';



const CustomReactMarkdown = ({ content, className }) => (

 <ReactMarkdown

  className={className}

  remarkPlugins={[remarkGfm]}

  components={{

   // Custom renderers for table elements

   th: ({ node, ...props }) => <th className="th" {...props} />,

   td: ({ node, ...props }) => <td className="td" {...props} />,

   // Add other custom renderers as needed

  }}

 >

  {content}

 </ReactMarkdown>

);

Enter fullscreen mode Exit fullscreen mode

Styling

To make our typewriter and Markdown content look nice, I include some basic CSS:


.typewriter-effect {

 font-family: 'Courier New', Courier, monospace;

 white-space: pre-wrap;

}



.typing-indicator {

 display: inline-block;

 width: 10px;

 height: 20px;

 background-color: currentColor;

 animation: blink 1s step-start infinite;

}



@keyframes blink {

 50% {

  opacity: 0;

 }

}



/* Add styles for the table components from CustomReactMarkdown here */

.table-bordered {

 border: 1px solid #e9ecef;

 border-radius: 0.25rem;

 width: 100%;

}



.th, .td {

 background-color: #f8f9fa;

 border: 1px solid #e9ecef;

 padding: 0.75rem;

 text-align: left;

}

Enter fullscreen mode Exit fullscreen mode

Conclusion

By combining React's state management and effect hooks with react-markdown, I've created a versatile typewriter effect component that can handle Markdown-formatted text. This effect can add a touch of dynamism and interactivity to your applications, making your content stand out.

Experiment with the TypewriterEffect component by adjusting the typingSpeed prop or by using different Markdown

Top comments (0)