Wagmi useContractEvent监听器无法访问useState变量求助
问题分析与解决方案
这是典型的React闭包陷阱问题。useContractEvent的监听器函数在组件首次渲染时被创建,它捕获了当时的hash状态(初始值是undefined)。当你调用setHash更新状态后,组件会重新渲染,但旧的监听器函数依然持有旧的闭包上下文,访问的还是最初的undefined,而非更新后的hash值。
方案一:使用useRef保存最新的hash值
用useRef存储hash的最新值,ref的.current属性不受闭包限制,随时能拿到更新后的值:
import { useState, useRef, useEffect } from 'react'; import { useContractEvent, useContractWrite } from 'wagmi'; const [hash, setHash] = useState<`0x${string}` | undefined>(); const hashRef = useRef<`0x${string}` | undefined>(undefined); // 当hash更新时同步到ref useEffect(() => { hashRef.current = hash; }, [hash]); useContractEvent({ address: contract.address as `0x${string}`, abi: contract.abi, eventName: "SomeEvent", listener(log) { console.log(hashRef.current); // 能获取最新的hash值 if (log[0]?.transactionHash !== hashRef.current) return; // 后续逻辑可正常执行 }, }); const { write } = useContractWrite({ address: contract.address as `0x${string}`, abi: contract.abi, functionName: "someFunction", args: [], onSuccess(data) { setHash(data.hash); }, }); return ( <button onClick={() => write?.()}> Go </button> );
方案二:给useContractEvent添加依赖项触发监听器重建
如果wagmi版本支持给useContractEvent传入依赖数组,可将hash加入依赖,这样hash更新时会重新创建监听器,新监听器能捕获最新的hash值:
import { useState } from 'react'; import { useContractEvent, useContractWrite } from 'wagmi'; const [hash, setHash] = useState<`0x${string}` | undefined>(); useContractEvent({ address: contract.address as `0x${string}`, abi: contract.abi, eventName: "SomeEvent", listener(log) { console.log(hash); // 能获取最新的hash值 if (log[0]?.transactionHash !== hash) return; // 后续逻辑可正常执行 }, }, [hash]); // 添加hash作为依赖 const { write } = useContractWrite({ address: contract.address as `0x${string}`, abi: contract.abi, functionName: "someFunction", args: [], onSuccess(data) { setHash(data.hash); }, }); return ( <button onClick={() => write?.()}> Go </button> );
注意:若你的wagmi版本不支持useContractEvent的依赖参数,优先选择方案一。
内容的提问来源于stack exchange,提问作者0xRLA
相关产品推荐
相关产品推荐

