React 父子组件传递的NFT元数据变量为空问题修复
问题原因
- NFT组件props接收语法错误:React函数组件的所有props统一存放在第一个入参对象中,原代码写为
const NFTCard = ({name}, {image}),仅从props中解构了name字段,image是从不存在的第二个入参里解构的,始终为undefined,是字段显示为空的核心原因。 - State更新后同步打印为空是React固有机制导致:React对state更新做异步批处理,调用
setName、setImage后,当前函数闭包内的name、image仍为更新前的初始空值,立刻执行console.log必然打印空值,不代表接口没拿到数据。如果需要拿到更新后的state值,用useEffect监听对应字段即可。 - Navbar直接操作DOM取输入值不符合React开发规范,容易出现取值不同步的问题。
修复后完整代码
App.js
新增useEffect监听state变化,值更新完成后再打印;新增异常捕获和空持仓判断,避免地址无效、地址无对应NFT时代码报错。
import { useState, useEffect } from 'react' import Navbar from './Navbar' import NFT from './NFT' // 需提前引入项目内的abi定义、ethers依赖 function App() { const [name, setName] = useState("") const [image, setImage] = useState("") // 监听name、image变化,值更新后执行逻辑 useEffect(() => { console.log('当前NFT名称:', name) console.log('当前NFT图片:', image) }, [name, image]) const getNFT = async (address) => { try { const provider = new ethers.providers.Web3Provider(window.ethereum) const contractAddress = "0x49cF6f5d44E70224e2E23fDcdd2C053F30aDA28B" const contract = new ethers.Contract(contractAddress, abi, provider) const holdCount = await contract.balanceOf(address) if (parseInt(holdCount) === 0) { alert('该地址未持有对应系列NFT') return } const tokenId = parseInt(await contract.tokenOfOwnerByIndex(address, 0)); const tokenUri = await contract.tokenURI(tokenId); const tokenMetaData = await fetchMetaData(tokenUri); setName(tokenMetaData.name) setImage(tokenMetaData.image) } catch(err) { console.error('查询NFT失败:', err) alert('查询失败,请检查输入地址是否正确、钱包是否切换到对应网络') } } const fetchMetaData = async (tokenUri) => { // 如果是IPFS开头的uri无法直接请求,可自行替换为公共IPFS网关前缀 const res = await fetch(tokenUri) const data = await res.json() return data } return ( <div className="App"> <Navbar getNFT={getNFT}/> <NFT name={name} image={image}/> </div> ); } export default App
Navbar.jsx
改为React受控组件管理输入框值,不再直接操作DOM取值,修复取值不同步问题。
import { useState } from 'react' const Navbar = ({getNFT}) => { const [inputAddress, setInputAddress] = useState('') const handleSearch = event =>{ event.preventDefault() if(!inputAddress.trim()){ alert("请输入钱包地址") return } getNFT(inputAddress.trim()) } return ( <div className="Navbar"> <div className="SearchField"> <input type="text" className="SearchBar" placeholder="0x..000" value={inputAddress} onChange={(e) => setInputAddress(e.target.value)} /> <button type="button" className='SearchButton' onClick={handleSearch}>Load</button> </div> </div> ) } export default Navbar
NFT.jsx
修正props解构语法,新增空状态占位,避免数据未加载时显示空白。
const NFTCard = ({name, image}) => { if (!name || !image) { return <div className='NFTCard'>输入地址后点击Load查询NFT</div> } return ( <div className='NFTCard'> <p className="name">{name}</p> <img src={image} alt={`${name}.png`} /> </div> ) } export default NFTCard
内容的提问来源于stack exchange,提问作者tintlingf
相关产品推荐
相关产品推荐

