Search code examples
reactjswebweb-development-server

Why am I getting double letters after using ityped package in React.js?


When using the ityped package for my react.js website, it's showing double letters instead of one. Screenshot: https://ibb.co/pd6GmHQ While running once without the backDelay and backSpeed it was running fine by showing only one character. After removing both backDelay and backSpeed it is not running properly, i.e. its showing double digits. I'm sorry if its a stupid question, I'm a newbie. This is my jsx file:

import React, { useEffect, useRef } from 'react'
import "./intro.scss"
import { init } from 'ityped'

export default function Intro() {

  const textRef = useRef();

  useEffect(()=>{
    init(textRef.current,{
      showCursor: true,
      backDelay: 1500,
      backSpeed:60,
      
      strings: ["Developer","Designer","Content Creator"],
    });

  },[]);

  return (
    <div className="intro" id="intro">
        <div className="left">
          <div className="imgContainer">
            <img src="assets/smit.jpg" alt="" />
          </div>
        </div>
        <div className="right">
          <div className="wrapper">
            <h2>Hi there, I'm</h2>
            <h1>Smit Thakkar</h1>
            <h3>Freelance <span ref ={textRef}></span></h3>
          </div>
          <a href="#probackground">
          <img src="assets/down.png" alt="" />
          </a>
        </div>
    </div>
  )
}

Solution

  • The duplication problem is a combination of two main factors:

    1.) This ityped package operates at the DOM level, which is discouraged in React, since it utilizes a virtual DOM that expects to be updated by updating React state. While this package can and does work, you're going to find that it duplicates when using StrictMode and useEffect -- in development, strict mode invokes useEffect twice; as a result, invokes init twice.

    2.) The other reason it duplicates is because it uses setInterval that isn't cleaned up on a hot reload. So every time you make a change to the component, it'll duplicate the init functionality as shown here (make any change to the App.js file and notice that a new instance of init occurs every time a hot reload occurs; on that note, this example uses a hack work-around using an isLoading global variable, which I'd highly discourage using in your project).

    Recommendations in order of hierarchy:

    A.) Don't use the package at all.

    B.) Don't use the package and instead develop the same functionality using React state/React life cycles that will clean itself up on hot reload/component unmount.

    C.) Use the package and deal with the duplication in development, but know that this may not occur in production. Although... the fact that this package doesn't do any cleaning up on a component unmount should be disconcerting and may cause problems with MPAs (multi page applications), where the component is unmounted/remounted -- which may cause duplication issues in production. Even more disconcerting is that this package doesn't have any guard against the element being undefined, so it'll throw errors as well.