useEffect内执行setState后state返回undefined无法使用问题咨询
问题本质
- useState初始化时没有赋值,首次渲染时
tokens的默认值就是undefined - useEffect在组件首次挂载完成后才触发执行,内部的
getSupportedTokens是异步接口请求,setTokens要等接口返回后才会执行触发重渲染,所以首次渲染周期内所有读取tokens的操作拿到的都是初始的undefined - 控制台打印对象能看到完整值是浏览器控制台的引用机制导致:打印时记录的是对象的引用,等你手动点开控制台展开对象时,接口已经请求完成、状态已经更新,所以展示的是最新值,如果你打印
console.log(JSON.stringify(tokens))就能看到首次输出是undefined
修复方案
- 给useState设置合理的初始值,避免初始undefined
- 所有用到
tokens的位置增加非空判断,比如可选链操作符,或者条件渲染 - 调整
listAvailableTokens的定义顺序,避免函数提升导致的调用报错
修复后代码示例
function App() { // 给初始状态设为空对象,也可以根据实际业务需要设为[]或者null const [tokens, setTokens] = useState({}); console.log(tokens) useEffect(() => { // 先定义listAvailableTokens,再在init里调用,避免函数表达式无提升导致的报错 const listAvailableTokens = async () => { const result = await Moralis.Plugins.oneInch.getSupportedTokens({ chain: "eth", // 要使用的区块链(eth/bsc/polygon) }); const tokensObject = result.tokens; console.log(tokensObject) setTokens(tokensObject); }; async function init() { await Moralis.initPlugins(); await Moralis.enable(); await listAvailableTokens(); } init(); }, []); // 其他组件用到tokens时加判断,示例: // return ( // <div> // {Object.keys(tokens).length > 0 && <TokenList tokens={tokens} />} // </div> // ) }
子组件使用注意
如果要把tokens传递给子组件使用,子组件内部读取属性时统一用可选链写法:tokens?.属性名,避免状态还没更新完成时报读取属性的错误。
内容的提问来源于stack exchange,提问作者JimJam
相关产品推荐
相关产品推荐

