问题描述
当我使用Websocket接收数据并将其更新到UI时,我会避免重新渲染组件。我有一个名为A的组件,并在其中使用Websocket来接收实时消息,然后将其显示给UI。我这样使用“ useEffect”钩子:
function User() {
let ws = new Websocket(host);
let [users,setUser] = useState([]);
useEffect(() => {
let message = [];
ws.onmessage = evt => {
message = JSON.parse(evt.data);
setUser(message);
}},[users]);
return (
<div className="user-table">
<Table users={users} />
</div>
)
}
由于Websocket经常有新数据(1秒),因此导致组件始终更新。那么,有什么办法可以避免这个问题? (缓存或类似的内容)
解决方法
这里的问题不是套接字本身,而是您的useEffect
依赖项数组包含一个状态,并且useEffect
回调添加了一个侦听器,并且该回调更改了状态的事实。每次调用setUser
时,users
都会发生变化-并且users
发生变化时,useEffect
会再次运行,因为其依赖项之一已更改。
从依赖项数组中删除users
,仅在useEffect
中声明套接字一次,这样您只有一个套接字(每个User
,至少...)一次活跃。
function User() {
const [users,setUsers] = useState([]);
useEffect(() => {
const ws = new Websocket(host);
ws.onmessage = evt => {
setUsers(JSON.parse(evt.data));
};
// Close socket on unmount:
return () => ws.close();
},[]); // <-- empty dependency array; only run callback once,on mount
return (
<div className="user-table">
<Table users={users} />
</div>
);
}
还请注意:
- 在ES6中最好在
let
之上preferconst
- 要减少错误,请适当命名变量-如果您有多个用户,请使用
users
和setUsers
。 (如果只有一个用户,则使用user
和setUser
)
如果有多个User
的机会,最好只在父对象中一次创建一个套接字,然后将其作为道具传递;这样,您将不会创建多个插座,它们都可以做相同的事情。