回应:公式文档中的“在自定义钩子中重用逻辑”的示例样本行为异常

由於反應應用程序公式文件中的「在自訂鉤子中重用邏輯」代碼示例的運作看起來很奇怪,所以我進行了修正。具體來說,這是關於「在鉤子之間傳遞反應式值」的 CodeSandbox 代碼。屏幕上每3秒會顯示一個通知。我完全不理解它與文件內容的相關性。

通知是通过setInterval()函数进行显示的。

通知模块(chat.js)中使用了setInterval()来模拟与服务器的连接。与自定义钩子没有直接关系。让我们简要地将清除计时器的clearInterval()调用也一并剔除掉。

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:在Hooks之间传递响应式值01
链接:https://codesandbox.io/s/react-passing-reactive-values-between-hooks-01-vw26qp

通知中显示连接信息

阅读公式文档的解释,这已经足够了。但是,既然已经安装了显示通知的库Toastify JS,不使用它也有点可惜。因此,我尝试将控制台输出的信息(connectionInfo)作为通知显示出来(示例002)。

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;
		},

	};
}
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:在Hooks之间传递反应性值02

将代码中的效果剪裁到定制的钩子中。

再来看看我们的官方文档中关于自定义钩子的主题,做一些逻辑的提取工作吧。

将ChatRoom组件的效果直接移至新的自定义钩子useChatRoom中。我们决定从参数对象中接收serverUrl和roomId。

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组件来说,不再需要效果。只需将serverUrl和roomId作为参数对象传递给自定义钩子useChatRoom并调用即可(示例003)。逻辑被分离出来,代码会变得更易读。

// 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:在Hooks之间传递响应式值03

引入 TypeScript

供参考,我们在示例004中引入了TypeScript并进行了类型化。同时还稍微整理了一下代码。

样本004■React:在钩子之间传递响应式值04

在公式样本中,为什么会包含那样多的多余代码仍然是个谜。考虑到最初制作的示例已经做了修订,定制钩子的主题似乎并没有任何关联。这应该是在浏览器中一眼就能发现的。很可能是因为时间很紧迫。

广告
将在 10 秒后关闭
bannerAds