React父子组件属性传递异常问题求助
主组件向子组件传递对象值失败的问题
我开发了一个从丹麦国家数据提供商SDFI加载房产相关数据的简单站点,已根据反馈简化代码并解构了props组件,但目前遇到了主组件向子组件传递正确值的问题。
在主组件AsyncSearch中调试时,grund.grundareal的值是正确的(即它是一个包含grundareal属性为某整数的对象),但传递到子组件ResultsDisplay后,它仅显示为空对象。
主组件代码(Search.js)
import { Container } from "react-bootstrap"; import { useState } from "react"; import { AsyncTypeahead } from "react-bootstrap-typeahead"; import ResultsDisplay from './ResultsDisplay'; const SEARCH_URI = "https://api.dataforsyningen.dk/autocomplete"; const AsyncSearch = () => { const [isLoading, setIsLoading] = useState(false); const [options, setOptions] = useState([]); const [found, setFound] = useState(false); const [hest, setHest] = useState([]) const handleSearch = async (query) => { setIsLoading(true); const response = await fetch(`${SEARCH_URI}?q=${query}&type=adresse`); const addresses = await response.json(); setOptions(addresses); console.log(addresses); setIsLoading(false); }; const handleChange = async (selected) => { if (selected === undefined || selected.length == 0 ) return; const s = selected[0] const aga = s.data.adgangsadresseid; let res; if (s.data.adgangsadresseid === undefined) { res = await fetch(`/bolig/${selected[0].data.id}`); } else { res = await fetch(`/bolig/${selected[0].data.adgangsadresseid}`); } let searchResults = await res.json(); console.log(`seachresults: ${searchResults}`) setHest(searchResults); setFound(true); } // Bypass client- side filtering by returning `true`. Results are already // filtered by the search endpoint, so no to do>it again. const filterBy = () => true; return ( <> <AsyncTypeahead filterBy={filterBy} id="async-load" isLoading={isLoading} labelKey="forslagstekst" onChange={handleChange} minLength={3} onSearch={handleSearch} options={options} placeholder="Indtast adresse" renderMenuItemChildren={(opt) => ( <> <span>{opt.tekst}</span> </> )} /> <ResultsDisplay hest={hest} /> </> ); } export default AsyncSearch;
子组件代码(ResultsDisplay.js)
import { useState } from "react" import { Container } from 'react-bootstrap'; const ResultsDisplay = ({hest}) => { console.log("LOL"); return( <> <Container> <h2>Grund</h2> <p>{hest.grund.grundareal}</p> </Container> {hest.bygninger.map((h, i) => { return ( <Container> <h2>Bygning</h2> <p>Opfoerelsesaar: {h.byg026Opførelsesår}</p> <p>Antal etager: {h.byg054AntalEtager}</p> <p>Bygningens anvendelse: {h.byg021BygningensAnvendelse}</p> <p>Varmeinstallation: {h.byg056Varmeinstallation}</p> <p>Samlede boligareal: {h.byg039BygningensSamledeBoligAreal}</p> <p>Bebygget areal: {h.byg041BebyggetAreal}</p> <p>Kommunekode: {h.kommunekode}</p> <p>Jordstykke: {h.jordstykke}</p> <p>Grund: {h.grund}</p> </Container>); })} </> ); } export default ResultsDisplay;
问题分析与解决方案
1. 初始状态类型不匹配
你在主组件中初始化hest为数组[],但实际从接口获取的是对象类型的数据。React首次渲染子组件时,hest是数组,访问hest.grund会得到undefined,后续即使更新为对象,也会因为初始类型不匹配导致渲染异常。
修改主组件中hest的初始状态为对象:
const [hest, setHest] = useState({})
2. 子组件未做空值校验
接口请求未完成时,hest是空对象,直接访问hest.grund.grundareal或调用hest.bygninger.map会抛出错误,导致组件无法正常渲染,掩盖后续数据更新效果。
在子组件中添加空值判断:
const ResultsDisplay = ({hest}) => { console.log("LOL"); // 当hest为空或无grund属性时,不渲染对应内容 if (!hest || !hest.grund) return null; return( <> <Container> <h2>Grund</h2> <p>{hest.grund.grundareal}</p> </Container> {/* 先校验bygninger是否存在且为数组,再执行map */} {hest.bygninger?.map((h, i) => { return ( <Container key={i}> {/* 添加key属性,避免React警告 */} <h2>Bygning</h2> <p>Opfoerelsesaar: {h.byg026Opførelsesår}</p> <p>Antal etager: {h.byg054AntalEtager}</p> <p>Bygningens anvendelse: {h.byg021BygningensAnvendelse}</p> <p>Varmeinstallation: {h.byg056Varmeinstallation}</p> <p>Samlede boligareal: {h.byg039BygningensSamledeBoligAreal}</p> <p>Bebygget areal: {h.byg041BebyggetAreal}</p> <p>Kommunekode: {h.kommunekode}</p> <p>Jordstykke: {h.jordstykke}</p> <p>Grund: {h.grund}</p> </Container>); })} </> ); }
3. 接口响应日志输出问题
你在handleChange中用console.log(seachresults: ${searchResults}),字符串拼接会把对象转为[object Object],无法查看真实响应结构。改为直接打印对象:
console.log('searchResults:', searchResults);
4. 可选优化:用found状态控制子组件渲染
主组件已有found状态,可用来控制子组件渲染时机,避免初始空状态渲染:
// 主组件return中修改 {found && <ResultsDisplay hest={hest} />}
内容的提问来源于stack exchange,提问作者Anders
相关产品推荐
相关产品推荐

