javascript - 将 websocket ref 传递给子组件
问题描述
我已经在父组件中建立了一个 websocket 连接,并socket
使用useRef
. 现在,我将它传递socket
给道具中的子组件。我想在子组件中使用此套接字来发出组件特定事件并根据某些 websocket 事件更新特定于组件的某些状态变量。
父组件:
function Parent(props) {
const userId = props.userId;
const socket = useRef(null);
useEffect(() => {
if (userId) {
socket.current = services.establishSocketConnect(userId);
}
return () => {
socket.current.close();
};
}, []);
return (
<React.Fragment>
<Child socket={socket} />
</React.Fragment>
);
}
const mapStateToProps = (state) => ({
userId:
(state.userInfo && state.userInfo.user && state.userInfo.user._id) || null,
});
export default connect(mapStateToProps, null)(Parent);
子组件:
function Child(props) {
const { socket } = props;
useEffect(() => {
console.log('Child => socket', socket);
if (socket.current) {
console.log('attaching socket events');
}
}, []);
return <h1>Child</h1>;
}
const mapStateToProps = (state, otherProps) => {
return {
// ...
...otherProps,
};
};
export default connect(mapStateToProps, null)(Child);
在子组件中,socket.current
没有 websocket 连接。我知道在初始渲染时,该值将为空。所以,这就是 Child 组件最初收到的内容。因此,我尝试添加socket
,socket.current
以便useEffect
Child 组件在更改时重新渲染。但是,这并没有发生,因为可变对象不能用作依赖项useEffect
,我猜..
请提出解决此问题的方法。
使用Robin Zigmond 的解决方案和一些额外的日志记录。
家长
function Parent(props) {
const userId = props.userId;
const socket = useRef(null);
useEffect(() => {
console.log('Parent => (initial) socket', socket);
socket.current = services.establishSocketConnection(userId);
if (socket.current) {
socket.current.onopen = onWSOpenEvent();
}
let i = setInterval(() => console.log('Parent => (interval) socket', socket), 5000);
return () => {
clearInterval(i);
};
}, [userId]);
return (
<React.Fragment>
<Child socket={socket.current} />
</React.Fragment>
);
}
孩子
function Child(props) {
const { socket } = props;
useEffect(() => {
console.log('Child => (initial) socket', socket);
if (socket) {
console.log('attaching socket events');
}
let i = setInterval(() => console.log('Child => (interval) socket', socket), 5000);
return () => {
clearInterval(i);
};
}, [socket]);
return <h1>Child</h1>;
}
这没有用。以下是日志:
解决方案
问题是您将socket
作为道具传递给子组件 - 按照设计,它是一个可变对象,其current
属性会发生变化,同时保持整个对象的相同引用。但是当你将整个对象传递给子组件时,这与 React 道具不能很好地配合——因为当该current
属性发生变化时,React 不会“看到”这种变化(道具仍然和以前一样——a引用同一个对象),所以它不会重新渲染孩子。
解决方案非常简单 - 不要将可变对象作为道具传递,而只是传递current
您关心的属性:
<Child socket={socket.current} />
现在,每当您socket
在 Child 组件中引用 prop 时,它都应该具有实际的 websocket 连接。
编辑:如果您希望在子组件中记录当前套接字值,每次更改时,子组件useEffect
中的
useEffect(() => {
console.log('Child => socket', socket);
if (socket) {
console.log('attaching socket events');
}
}, [socket]);
推荐阅读
- r - XGB predict 在预测外部火车值时总是返回相同的值
- amazon-dynamodb - aws 胶水作业以导入 dynamodb 数据
- python-3.x - python中的黑名单href以删除垃圾站点
- php - 网页卷曲检索于 2021 年 8 月至 2021 年 9 月停止工作
- docker - 开发应用程序时读取 Docker 中 Scality\S3server 存储的访问权限
- x86 - 操作系统如何确保一个进程无法访问 x86 架构中全局描述符表中另一个进程的基本限制?
- python - 当用户标记某人时如何发送成员名称
- c# - 在stimulsoft中每页打印每条记录
- flutter - 如何在 Flutter pdf 中附加资产图像 (jpg/png):^3.6.0 包
- html - HTML Sending 在获取请求中发送不同的语言字符