React组件渲染空白求助:API请求正常但页面无内容
React表单提交后页面空白,API调用正常但组件不渲染数据
问题描述
提交表单后页面显示空白,但API调用返回了正确的JSON数据(结构如下),控制台能看到React元素被创建,但页面就是不渲染。
期望的API返回JSON结构:
[ { "trackName": "Beira de Piscina (Remix)", "trackUri": "spotify:track:6a0kQTjyGmfwBF0tLVgEha", "artistImage": "https://i.scdn.co/image/ab67616d0000b27366127aa6c868a01e97f62d64" }, { "trackName": "Beira de Piscina", "trackUri": "spotify:track:25XUxLporfgzl2rf2mtgmj", "artistImage": "https://i.scdn.co/image/ab67616d0000b2738e2cc04d7c1ed2beb3216ff2" } ]
以下是出现问题的组件代码:
import {useState} from "react"; export default function SearchTracks() { const [formSuccess, setFormSuccess] = useState(false) const [trackList, setTracklist] = useState() const handleSubmit = async (event: any) => { event.preventDefault() const data = { trackName: event.target.trackName.value } const endpoint = `http://myEndPoint:8080/tracks?trackName=${data.trackName}` const options = { method: 'GET', headers: { 'access-token': 'MyAccessToken' } } const response = await fetch(endpoint, options) const result = await response.json() setFormSuccess(true) setTracklist(result) }; const renderTrack = (trackListResponse) : any => { const myMap = new Map(Object.entries(trackListResponse)) return myMap.forEach((trackValue) => { return trackValue.map(track => { let value = buildTrackContainer(track) console.log(value) return value }) }) } const buildTrackContainer = (track) => { console.log("Building track: " + track.trackName) return <li key={track.trackUri}> <p>{track.trackName}</p> <p>{track.trackUri}</p> <img src={track.artistImage}/> </li> } return ( <div> {formSuccess ? <ul> { renderTrack({trackList}) } </ul> : <form onSubmit={handleSubmit}> <label htmlFor="trackName">Track Name</label> <input type="text" id="trackName" name="trackName" required/> <button type="submit">Submit</button> </form> } </div> ) }
控制台能打印出React元素,但页面空白,附控制台日志截图和页面结果截图。
问题原因与修复方案
核心问题1:forEach无返回值导致渲染内容为空
renderTrack函数中使用myMap.forEach(...),但forEach方法不会返回任何值(始终返回undefined),即便内部调用trackValue.map生成了React元素数组,最终也无法传递给渲染层。
核心问题2:冗余的Map包装与参数传递
你传递给renderTrack的是{trackList}(一个包含trackList属性的对象),再用Object.entries转成Map完全多余——API返回的trackList本身就是数组,直接遍历即可。
修复后的代码
import {useState} from "react"; export default function SearchTracks() { // 初始化空数组,避免undefined引发的潜在错误 const [formSuccess, setFormSuccess] = useState(false) const [trackList, setTracklist] = useState<any[]>([]) const handleSubmit = async (event: any) => { event.preventDefault() const trackName = event.target.trackName.value const endpoint = `http://myEndPoint:8080/tracks?trackName=${trackName}` const options = { method: 'GET', headers: { 'access-token': 'MyAccessToken' } } const response = await fetch(endpoint, options) const result = await response.json() // 先更新数据再切换状态,确保渲染时已有数据 setTracklist(result) setFormSuccess(true) }; // 直接遍历trackList数组生成元素 const renderTracks = () => { return trackList.map(track => buildTrackContainer(track)) } // 添加参数类型定义,提升代码可读性与类型安全 const buildTrackContainer = (track: {trackName: string; trackUri: string; artistImage: string}) => { return ( <li key={track.trackUri}> <p>{track.trackName}</p> <p>{track.trackUri}</p> {/* 添加alt属性,优化可访问性 */} <img src={track.artistImage} alt={`${track.trackName} artist image`} /> </li> ) } return ( <div> {formSuccess ? ( <ul>{renderTracks()}</ul> ) : ( <form onSubmit={handleSubmit}> <label htmlFor="trackName">Track Name</label> <input type="text" id="trackName" name="trackName" required/> <button type="submit">Submit</button> </form> )} </div> ) }
额外优化点
- 初始化
trackList为空数组,避免初始状态为undefined的潜在问题 - 调整状态更新顺序,确保渲染时数据已准备完毕
- 给函数参数添加类型定义,提升代码健壮性
- 为图片添加
alt属性,符合Web可访问性标准
内容的提问来源于stack exchange,提问作者João Fulgêncio
相关产品推荐
相关产品推荐

