【React】コードを書いているようなアニメーションを作成する


概要

Next.jsでmarkdownブログを作ったのですが、その中でコードを書いているようなアニメーションを実装してみたので、共有します。
カスタムフックとして切り出せたので誰でも使用出来ます。

完成したもの

自作ブログで見れます。

カスタムフック

setIntervalで文字列の長さのstateをアップデートしているだけです。

setStep.ts
import { useEffect, useRef, useState } from 'react';

export const useStep = (text: string, stepTime: number) => {
  const [length, setLength] = useState(0);
  const lengthRef = useRef(length);

  useEffect(() => {
    lengthRef.current = length;
  }, [length]);

  useEffect(() => {
    const timer = setInterval(() => {
      setLength(lengthRef.current === text.length ? lengthRef.current : lengthRef.current + 1);
    }, stepTime);
    return (): void => clearInterval(timer);
  }, []);

  return text.slice(0, length);
};

Refを用いないと、クロージャの働きによってsetInterval内のlengthの値が変わりません。
setIntervalした場合、useEffectのreturnにタイマー解除のコールバックを忘れずに。

コンポーネント

コードと、間隔を指定して、返り値をrenderするだけです。

LiveCode.tsx
import React from 'react';

import { useStep } from '../../hooks/useStep';
import { CodeBlock } from '../Post/MarkDownViewer';

type Props = {
  code: string;
  language: string;
};

export const LiveCode: React.FC<Props> = props => {
  const codeState = useStep(props.code, 35);
  return (
    <>
      <CodeBlock value={codeState} language={props.language} />
    </>
  );
};

CodeBlockコンポーネントでは、React-Markdownreact-syntax-highlighterを使用しています。

まとめ

React楽しすぎますね。
やっぱりカスタムフックで機能とコンポーネントを分けられるところがクールです。