React - 回调的关闭问题
Posted
技术标签:
【中文标题】React - 回调的关闭问题【英文标题】:React - closure issue with a callback 【发布时间】:2020-08-26 02:52:17 【问题描述】:我一直对我的猜测是关闭有一些问题,我只是在猜测,因为看起来我并不像我想象的那样理解它。问题来了:
我正在尝试使用 Stomp 建立 Web 套接字连接。它的工作方式是,你创建一个 stomp 客户端
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)
函数一次,我怎样才能传入反映我状态的回调?
谢谢!
【问题讨论】:
请提供所涉及组件的完整代码。谢谢 【参考方案1】:您是否尝试过从回调中调用一个函数,然后从该函数记录状态?
const myCallBack = (message) =>
onMessageReceived();
const onMessageReceived = () =>
console.log(counter);
也许?
【讨论】:
您编写的代码正是我拥有的代码并且不起作用。看起来当回调创建时它指向count:0,即使count在第二次useEffect期间多次更新,回调仍然打印count:0 重点是使用 useEffect 两次,因为它只想运行一次。你甚至读过我的回答吗?即使代码不同,代码如何完全相同?您没有包含完整的代码,所以我只是根据您提供的片段进行猜测。请记住,我正在尝试在这里帮助您,所以也请尝试为您付出一点努力。 我很抱歉。至于您提出的第一点,是的,我们无法从仅在组件安装时运行的 useEffect 挂钩中更改计数器的状态,并且即使我从外部更改它也应该获得正确的值,我会以为我应该,但显然我没有得到正确的值。至于我的意思是这正是我所拥有的代码,第一个 useEffect 就像问题中所述,我说当用户使用应用程序时,计数器变量会改变。在依赖数组中使用另一个带有counter
的 useEffect 是我的做法。
好的,我明白了,抱歉我误解了你的意思。同样,发布您的完整代码可以避免这种情况。如果您可以提供完整的组件代码,那将会很有帮助。我知道这并不总是可能的。因此,您正在通过调用 setCount 或 w/e 来修改计数,而您的回调仍在记录 0,对吗?另外,你有没有尝试从 useEffect 中移除依赖数组,然后会发生什么?
因此,如果回调在订阅完成后执行,并且订阅仅在挂载时运行一次(当计数为 0 时),那么您不应该得到任何其他值而不是 0,因为回调只是跑一次,对吧?而且无论您更新状态和重新渲染多少次,都不会再次调用该回调。对吗?以上是关于React - 回调的关闭问题的主要内容,如果未能解决你的问题,请参考以下文章
前端学习(3129):react-hello-react之回调形式的ref的次数问题