1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FizzBuzzボタンを作りながらReact Hooksを学ぶ 第6回

Last updated at Posted at 2019-08-03

FizzBuzz ボタンを作りながら React Hooks を学んでいきます。
目次はこちら

Custom Hook を作る

前回まででひととおり React Hooks を使った FizzBuzz ボタンは完成しました。
今回は Custom Hook を作ります。

Hook を組み合わせて独自の Hook を作ることができます。これを Custom Hook と呼びます。
今回は簡単な Custom Hook を作ります。

前回、マウントとアンマウント時の処理を Effect Hook を使って作りました。

FizzBuzz.tsx
const FizzBuzz: React.FC<Props> = React.memo((props: Props) => {
  ...
  useEffect(() => {
    console.log('mount');
    return () => console.log('unmount');
  }, []);
  ...

useEffect の第1引数にマウント時の処理を指定し、その戻り値にアンマウント時の処理を指定します。
これは少しわかりにくいので、第1引数にマウント時の処理、第2引数にアンマウント時の処理を指定するような関数(useMount)を作ります。

FizzBuzz.tsx
const useMount = (
  mount: () => void,
  unmount?: () => void
): void | (() => void) => {
  useEffect(() => {
    mount();
    return unmount;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
};

const FizzBuzz: React.FC<Props> = React.memo((props: Props) => {
  ...
  useMount(() => console.log('mount'), () => console.log('unmount'));
  ...

ここで注意しなければいけないのは useEffect の第2引数です。
修正前の実装の通り、第2引数には [] を渡せば良いのですが、VS Code でファイルを保存すると、eslint-plugin-react-hooks が補完をして [mount, unmount] となってしまいます。
これでは期待通りの動作になりませんので、補完されないようにコメントを記述しています。

useMount は JSX を使用していませんので、別ファイルに切り出す際には拡張子を ts としておきます。

hooks.ts
import { useEffect } from 'react';

export const useMount = (
  mount: () => void,
  unmount?: () => void
): void | (() => void) => {
  useEffect(() => {
    mount();
    return unmount;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
};

↓こんな感じで使います。

FizzBuzz.tsx
import React, { useState, useCallback } from 'react';
import FizzBuzzView from './FizzBuzzView';
import { fizzBuzz } from './common';
import { useMount } from './hooks';

type Props = {
  // props で count の初期値を受け取る
  initialCount: number;
};

const FizzBuzz: React.FC<Props> = React.memo((props: Props) => {
  console.log('render');
  const [count, setCount] = useState(props.initialCount);
  // eslint-disable-next-line no-shadow
  const plus1 = useCallback(() => setCount(count => count + 1), []);
  const clear = useCallback(() => setCount(props.initialCount), [
    props.initialCount,
  ]);
  useMount(() => console.log('mount'), () => console.log('unmount'));
  const message = fizzBuzz(count);

  return (
    <FizzBuzzView count={count} message={message} plus1={plus1} clear={clear} />
  );
});

export default FizzBuzz;

今回作成したソースコードはこちら
次回はもうひとつ Custom Hook を作ります。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?