MadnessTony
@MadnessTony
Web Developer

Как реализовать анимацию набора текста?

Сделал компонент для анимации текста, который будет писать путь при обновлении location.

Компонент для анимации
import React, { useEffect, useState } from 'react';

interface IText {
  text: string;
}

export const Typewriter: React.FC<IText> = ({ text }) => {
  const [txt, setTxt] = useState('');

  useEffect(() => {
    const timeout = setTimeout(() => {
      console.log(text, txt);
      if (text !== '' && text !== txt) {
        setTxt('');
      }
      setTxt(text.slice(0, txt.length + 1));
    }, 100);
    return () => {
      clearTimeout(timeout);
      console.log('end');
    };
  }, [txt, text]);

  return <>{txt}</>;
};

Компонент в котором происходит смена роута
import { NavLink, useLocation } from 'react-router-dom';

import { Typewriter } from 'components/atoms/Typewriter';

import './Header.scss';

export const Header = () => {
  const location = useLocation();

  const formatLocation = (location: string): string => {
    if (location === '/') {
      return '';
    }
    location = location.substring(1);
    return `${location} /`;
  };

  return (
    <header className="header">
      <div className="header__container">
        <NavLink className="header__logo" to="/">
          {<Typewriter text={formatLocation(location.pathname)} />}
        </NavLink>
        <nav className="nav">
          <NavLink className="nav__link" to="/about">
            About /
          </NavLink>
          <NavLink className="nav__link" to="/skills">
            Skills /
          </NavLink>
        </nav>
      </div>
    </header>
  );
};

Собственно анимация работает только при смене пустого роута на страницу, но если переключится между страницами, то он выводится без анимации.
  • Вопрос задан
  • 383 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега React
function Typewriter({ text }) {
  const [ length, setLength ] = useState(0);

  useEffect(() => {
    setLength(0);

    const interval = setInterval(setLength, 100, length => {
      if (++length >= text.length) {
        clearInterval(interval);
      }

      return length;
    });

    return () => clearInterval(interval);
  }, [ text ]);

  return <div>{text.slice(0, length)}</div>;
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы