Type writer Effect like ChatGPT with React
Tags: react, chatgpt, webdev, javascript
Published: 2024-04-04 07:04:47

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:



```bash

npm create vite@latest my-typewriter-effect

cd my-typewriter-effect

npm install

```



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



```bash

npm install react-markdown remark-gfm

```



### 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:



```jsx

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>

 );

};

```



### 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.



```jsx

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>

);

```



### Styling



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



```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;

}

```



### 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