Abstract:
This post shares a developer’s notes and tips for implementing a smooth, multi-paragraph typing animation effect in React, complete with a feature to skip the animation. Key aspects covered include state management using React hooks (useState
, useEffect
, useCallback
), alternatives to direct DOM manipulation, handling user events to skip typing, and managing internationalized text with react-i18next
.
Estimated reading time: 3 minutes
(Notes for myself - you can check out the effect at 8bitoracle.ai)
Getting a typing effect to work properly can be quite challenging. I have a few paragraphs of text and wanted to create a typing effect for it, allowing the user to skip the animation. If a user presses a spacebar or clicks on a paragraph, the current paragraph should complete instantly, and the next one should begin typing.
A few tips:
-
Directly changing the page structure with DOM manipulation can often cause bugs. It is usually better to update HTML elements by changing their content or visibility through React’s state.
-
It’s simpler to create a typing effect by showing and hiding parts of the text, instead of actually typing out characters one by one or copying them from a hidden place.
Here are the main lessons from the code I used to create a typing effect in React. This effect works for several paragraphs and lets the user skip the animation at any time:
-
State Management:
- Use the
useState
hook to manage the state of the current paragraph’s index (currentParagraphIndex
) and the number of characters currently visible (visibleCharacters
). - Update these state variables as needed to control the typing and keep track of its progress.
- Use the
-
Parsing Paragraphs:
- Get the paragraphs from the
backstory
data. Use the selected language to pick the right text, using JavaScript’sObject.entries
andmap
methods. - Make an array of paragraph items. Each item should have an
id
andtext
to make them easier to show and manage.
- Get the paragraphs from the
-
Typing Effect:
- Use the
useEffect
hook to control the typing effect based on thevisibleCharacters
andcurrentParagraphIndex
state variables. - Use a timer (
setTimeout
) to slowly show more characters in the current paragraph. - After the current paragraph is fully typed, wait a moment and then start typing the next one.
- To prevent problems (memory leaks), clear the timer if the component is removed or if its dependencies change.
- Use the
-
Skipping Animation:
- Create a
skipTypingAnimation
function. This lets the user skip the typing and see the whole current paragraph at once. - Use the
useCallback
hook to memoize this function (meaning React will reuse the same function instance if its dependencies haven’t changed), which can help optimize performance.
- Create a
-
Event Handlers:
- Set up event handlers so that pressing a key (like spacebar) or touching/clicking the screen runs the
skipTypingAnimation
function. - Use
useEffect
hooks to add these event listeners when needed and remove them when not, based on certain conditions (dependencies).
- Set up event handlers so that pressing a key (like spacebar) or touching/clicking the screen runs the
-
Rendering:
- Go through the
paragraphs
array and show each paragraph as a separate<p>
HTML element. - Figure out which parts of each paragraph to show or hide. Use the
currentParagraphIndex
andvisibleCharacters
state values for this. - Show the visible text. For the current paragraph, also show a typing cursor. You can also include the hidden text but with a ‘hidden’ style so it’s not seen until typed.
- Make each paragraph clickable or touchable to let users skip the animation for that paragraph.
- Go through the
-
CSS Styling:
- Use CSS classes to style the text, the cursor, and the hidden parts.
- Use CSS animations or transitions to make the typing cursor blink.
-
Performance Optimization:
- Use
useCallback
(for functions) anduseMemo
(for values) hooks to memoize parts of your component. This means React reuses them if their inputs haven’t changed, preventing unnecessary recalculations and improving performance. - Make rendering faster by only updating the parts of the component that change when the state changes.
- Use
-
Internationalization:
- Use the
useTranslation
hook from thereact-i18next
library to support different languages (internationalization). - Get the correct text translations from the
backstory
data, based on the chosen language.
- Use the
By using these ideas, you can build a typing effect in React that works well, is interactive, and supports multiple languages.