You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

改为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 21:15:44