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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 02:45:01