如何在useEffect
内设置连接,同时使用自定义钩子装饰该连接?在渲染期间,不允许在useEffect
内运行自定义挂钩,也不允许在ref.current
内运行.用react 友好的界面包装连接的正确方式是什么?
我认为在Reaction中建立WebSocket
连接的正确方法是使用useEffect
挂钩,如下所示
const connection = useRef(null);
useEffect(() => {
const ws = new WebSocket(socketUrl);
connection.current = ws;
return () => {
ws.close();
connection.current = null;
}
}, [socketUrl]);
以类似的方式,我设想创建一个RTCDataConnection
,它遵循与.send('...')
和open
、close
、error
和message
事件相同的连接接口.
我正在寻找一种方法,为这些连接提供一个类似react 的接口.我的 idea 类似于下面的定制useConnection
挂钩,它接受一个JavaScript Connection对象,并提供两个react 状态变量lastMessage
和readyState
,以及一个方法sendMessage
:
export function useConnection(connection) {
const [lastMessage, setLastMessage] = useState(null);
const [readyState, setReadyState] = useState(null);
const onReadyStateChange = useCallback(
(e) => {
console.info(e);
setReadyState(connection.readyState);
},
[setReadyState]
);
const onMessage = useCallback(
({ data }) => {
const message = JSON.parse(data);
setLastMessage(message);
},
[setLastMessage]
);
function sendMessage(message) {
const msgJSON = JSON.stringify(message);
connection.send(msgJSON);
}
useEffect(() => {
connection.addEventListener('open', onReadyStateChange);
connection.addEventListener('close', onReadyStateChange);
connection.addEventListener('error', onReadyStateChange);
connection.addEventListener('message', onMessage);
return () => {
connection.removeEventListener('open', onReadyStateChange);
connection.removeEventListener('close', onReadyStateChange);
connection.removeEventListener('error', onReadyStateChange);
connection.removeEventListener('message', onMessage);
};
}, [connection]);
return { lastMessage, readyState, sendMessage };
}
然而,我不知道如何正确地将挂钩应用于连接.
- 到了the rules of hooks,我打不通
useEffect
内线的useConnection
.它向我抛出"无效的钩子调用". - 我也不能引用
useEffect
之外的connection.current
,因为这违反了the rules ofuseRef
:在呈现期间不允许访问.current
属性.
所以我的问题是,我如何将连接和挂钩结合在一起?或者我应该使用一种完全不同的方法?