React组件与页面间状态传递异常:账户号传递后返回undefined如何解决
问题原因和修复方案
核心问题:activate是异步操作,调用后立即读取account拿到的是旧值
你现有代码在点击事件中同步调用activate()和handleClick(),第三方服务的激活操作(比如钱包授权、账户连接)都是异步逻辑,你调用activate()后立刻读取account时,第三方服务还未完成授权返回账户信息,所以拿到的是undefined。
次要问题:现有代码存在多处语法错误
你贴的specialbutton.js存在JSX括号配对错误、标签闭合错误、return多余数组、判断语法错误等问题,也可能导致状态传递异常。
状态更新的异步特性说明
React的setState是批量异步更新的,你在handleChildClick中调用setMMAccount后立即打印mmAccount拿到的是旧值属于正常现象,打印传入的参数就是拿到的新账户值,状态会在下一次渲染时完成更新。
修复后的specialbutton.js代码
import { useEffect } from 'react' function SpecialButton({ onAcctChange }) { // 不需要接收父组件的mmAccount,减少不必要的props依赖 const { activate, deactivate, account } = imported3rdpartystuff() // 监听第三方account状态变化,自动同步到父组件,避开异步读值问题 useEffect(() => { if (account) { onAcctChange(account) } }, [account, onAcctChange]) function handleConnect() { activate() } if (window.somestuff === true) { return ( <p> {!account ? ( <LoadingButton onClick={handleConnect}> Connect Here </LoadingButton> ) : ( <Button variant="contained" onClick={deactivate} > Disconnect: {account.substring(0,5)}...{account.slice(-4)} </Button> )} </p> ) } return null }
修复后的app.js代码
import { useState } from 'react' import { BrowserRouter as Router } from 'react-router-dom' function App() { const [mmAccount, setMMAccount] = useState(''); function handleChildClick(newAccount) { setMMAccount(newAccount) // 这里打印newAccount就是最新的账户值,打印mmAccount是旧值属于正常逻辑 console.log('new acct:', newAccount); } // 渲染层打印可验证状态是否更新成功 console.log('当前app中的mmAccount:', mmAccount) return ( <Router> <SpecialButton onAcctChange={handleChildClick}/> {/* 其他组件直接传递mmAccount即可使用最新值 */} </Router> ) }
可选的另一种修复方式
如果你一定要在点击回调中获取账户值,可以给异步的activate加await等待操作完成:
async function handleConnect() { await activate() // 等待激活完成后再读取account就已经是最新值了 onAcctChange(account) }
内容的提问来源于stack exchange,提问作者Alex Legault
相关产品推荐
相关产品推荐

