0
0

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 1 year has passed since last update.

React: 公式ドキュメント「カスタムフックでロジックを再利用する」のサンプルの動きがおかしい

Posted at

React公式ドキュメント「カスタムフックでロジックを再利用する」のコードサンプルの動きがどう見てもおかしいので直しました。具体的には、「フック間でリアクティブな値を渡す」のCodeSandboxのコードです。画面には3秒おきに通知が表示されます。ドキュメント本文の解説とどう関わるのかが、まったくわかりません。

通知はsetInterval()で表示されていた

通知はサーバーとの接続をシミュレートするモジュール(chat.js)に、setInterval()で表示されていました。カスタムフックの話に絡みそうにありません。クリーンアップのclearInterval()の呼び出しも含めて、さっくり除きましょう。

chat.js
export function createConnection({ serverUrl, roomId }) {

	// let intervalId;
	let messageCallback;
	return {
		connect() {
			console.log(
				'✅ Connecting to "' + roomId + '" room at ' + serverUrl + "..."
			);
			/* clearInterval(intervalId);
			intervalId = setInterval(() => {

			}, 3000); */
		},
		disconnect() {
			// clearInterval(intervalId);
			messageCallback = null;
			console.log(
				'❌ Disconnected from "' + roomId + '" room at ' + serverUrl + ""
			);
		},

	};
}

こうしたら、ドキュメントの解説もわかるようになりました(サンプル001)。画面に通知は表示されず、コンソールの出力で動きが確かめられます。画面のURLやチャットルームの選択を変更すると、チャットが再接続されるというサンプルです。

サンプル001■React: Passing reactive values between Hooks 01
https://codesandbox.io/s/react-passing-reactive-values-between-hooks-01-vw26qp

接続情報を通知で示す

公式ドキュメントの解説を読むにはこれで十分です。けれど、せっかく通知を表示するライブラリToastify JSがインストールされているのに、使わないのももったいないように思います。そこで、コンソール出力と同じ情報(connectionInfo)を通知としても示すようにしてみました(サンプル002)。

chat.js
export function createConnection({ serverUrl, roomId }) {

	return {
		connect() {
			const connectionInfo = `✅ Connecting to "${roomId}" room at ${serverUrl}...`;
			console.log(
				// '✅ Connecting to "' + roomId + '" room at ' + serverUrl + "..."
				connectionInfo
			);
			messageCallback && messageCallback(connectionInfo, 'white');
		},
		disconnect() {
			const connectionInfo = `❌ Disconnected from "${roomId}" room at ${serverUrl}`;
			// messageCallback = null;
			console.log(
				// '❌ Disconnected from "' + roomId + '" room at ' + serverUrl + ""
				connectionInfo
			);
			messageCallback && messageCallback(connectionInfo, 'dark');
			messageCallback = null;
		},

	};
}
ChatRoom.js
export default function ChatRoom({ roomId }) {

	useEffect(() => {

		// connection.on("message", (msg) => {
		connection.on("message", (msg, theme) => {
			// showNotification('New message: ' + msg);
			showNotification("New connection: " + msg, theme);
		});

	}, [roomId, serverUrl]);

}

サンプル002■React: Passing reactive values between Hooks 02
https://codesandbox.io/s/react-passing-reactive-values-between-hooks-02-mcp2ty

エフェクトのコードをカスタムフックに切り出す

もうひとつ、公式ドキュメントの主題であるカスタムフックへのロジックの切り出しまでやってしまいましょう。

コンポーネントChatRoomのエフェクトを、そのまま新たなカスタムフックuseChatRoomに移します。引数オブジェクトからは、serverUrlroomIdを受け取ることにしました。

useChatRoom.js
import { useEffect } from 'react';
import { createConnection } from './chat.js';
import { showNotification } from './notifications.js';

export const useChatRoom = ({ serverUrl, roomId }) => {
	useEffect(() => {
		const options = { serverUrl, roomId };
		const connection = createConnection(options);
		connection.on('message', (msg, theme) => {
			showNotification('New connection: ' + msg, theme);
		});
		connection.connect();
		return () => connection.disconnect();
	}, [roomId, serverUrl]);
};

ChatRoomコンポーネントに、もうエフェクトは要りません。カスタムフックuseChatRoomの引数オブジェクトに、serverUrlroomIdを渡して呼び出せば済むからです(サンプル003)。ロジックが切り分けられて、コードは読みやすくなったでしょう。

ChatRoom.js
// import { useState, useEffect } from "react";
import { useState } from "react";
import { useChatRoom } from "./useChatRoom.js";
// import { createConnection } from "./chat.js";
// import { showNotification } from "./notifications.js";

export default function ChatRoom({ roomId }) {

	/* useEffect(() => {

	}, [roomId, serverUrl]); */
	useChatRoom({ serverUrl, roomId });

}

サンプル003■React: Passing reactive values between Hooks 03
https://codesandbox.io/s/react-passing-reactive-values-between-hooks-03-4dpslt

TypeScriptを採り入れる

ご参考までに、TypeScriptを採り入れて型づけしたのがサンプル004です。少しコードも整理しました。

サンプル004■React: Passing reactive values between Hooks 04
https://codesandbox.io/s/react-passing-reactive-values-between-hooks-04-vmx36j

公式サンプルに、なぜあのような余分なコードが含まれていたのかは謎です。はじめにつくった作例が改定されたにしては、カスタムフックの主題には、絡むどころかかすりもしそうにありません。ブラウザでひと目見たら気づきそうなものです。おそらく、忙しかったのでしょう。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?