我一直在猜测什么是闭包方面遇到一些问题,我只是猜测,因为看起来我并没有像我想象的那样理解它。这是问题所在:
我正在尝试使用Stomp建立Web套接字连接。它的工作方式是,你创建一个踩踏客户端
let stompClient = Stomp.over(socket);
然后你订阅一些路由,传入路由并传入一个回调,当该路由被命中时,该回调将被调用
stompClient.subscribe("/topic/some-route",(message) => myCallback(message))
由于创建客户端似乎是一次性的事情,我决定将其放在数组中没有依赖项的useEffect
钩中,以便仅在组件挂载时创建客户端。
useEffect(() => {
//some unimportant setup
let stompClient = Stomp.over(socket);
stompClient.subscribe("/topic/some-route",(message) => myCallback(message))
}, [])
为了简单起见,我还在我的组件中保留了一些状态,假设我保留了这个:
const [counter, setCounter] = useState(0);
我希望我的回调做的是打印出状态,所以:
const myCallback = (message /* the message variable is unimportant here */ ) => {
console.log(counter);
}
现在,当用户使用应用程序时,counter
状态将发生变化,但每当触发回调时,它始终打印 0。使用我所拥有的闭包知识,我猜测...:(这是问题#1(
- 因为函数闭包(上下文这个词似乎更适合我(在创建函数时被初始化,所以函数将
counter
变量作为 0,这就是它总是打印 0 的原因。这种说法正确吗?
如果我将stompClient.subscribe("/topic/some-route",(message) => myCallback(message))
移动到useEffect
钩子之外,myCallback
函数将打印出当前状态,但是,考虑到这个.subscribe(...)
函数为我的 stomp 代理创建了一个全新的订阅,我最终会得到数百个订阅,每个状态更新一个,这显然不是解决方案。这让我想到了问题#2,
- 考虑到我只需要调用这个
.subscribe(message, callback)
函数一次,我如何传入一个反映我的状态的回调?
谢谢!
您是否尝试过从回调调用函数,然后从该函数记录状态?
const myCallBack = (message) => {
onMessageReceived();
}
const onMessageReceived = () => {
console.log(counter);
}
或?
以防有人遇到同样的问题。这可以通过 useRef(( 钩子来解决。
let stompClient = Stomp.over(socket);
const [counter, setCounter] = useState(0);
const stateRef = useRef();
// make stateRef always have the current count
// your "fixed" callbacks can refer to this object whenever
// they need the current value. Note: the callbacks will not
// be reactive - they will not re-run the instant state changes,
// but they *will* see the current value whenever they do run
stateRef.current = count;
useEffect(() => {
let stompClient = Stomp.over(socket);
stompClient.subscribe("/topic/some-route",(message) => myCallback(message))
}, [])
const myCallback = (msg) => {
console.log(stateRef.counter);
}
答案在这里找到