回应:公式文档中的“在自定义钩子中重用逻辑”的示例样本行为异常
由於反應應用程序公式文件中的「在自訂鉤子中重用邏輯」代碼示例的運作看起來很奇怪,所以我進行了修正。具體來說,這是關於「在鉤子之間傳遞反應式值」的 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
在公式样本中,为什么会包含那样多的多余代码仍然是个谜。考虑到最初制作的示例已经做了修订,定制钩子的主题似乎并没有任何关联。这应该是在浏览器中一眼就能发现的。很可能是因为时间很紧迫。