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

React多层子组件状态提升问题求助

解决React多层组件状态提升问题

要把Select选中的城市信息同步到Main组件的state,核心是通过回调函数逐层传递,把顶层的状态更新方法往下传给子组件,让子组件能触发顶层状态更新。具体修改步骤如下:

  • Main组件:给Search传递更新cityObj的回调函数
  • Search组件:接收回调函数并传递给Select
  • Select组件:提交时通过回调把选中的完整城市对象传给Main

修改后的Main.js

function Main() {
    const [cityObj, setCityObj] = React.useState(null); // 初始值设为null更合理
    return (
        <div className="container p-5 bg-primary">
            <i className='text-danger fw-bold'>Main component</i>
            <h2 className='m-3'>My React Weather Application</h2>
            {/* 传递setCityObj给Search,命名为onCitySelect */}
            <Search onCitySelect={setCityObj} />
            <hr />
            {/* 把cityObj传给Body组件使用 */}
            <Body cityObj={cityObj} />
        </div>
    );
}

修改后的Search.js

function Search(props) {
    const [searchTerm, setSearchTerm] = React.useState('');
    const [cityArray, setCityArray] = React.useState([]);
    // 清理冗余状态
    const Weather_API_key = '55c5392db030dbb75249aa1ff9b8a871';
    const url = 'http://api.openweathermap.org/geo/1.0/direct';

    const handleChange = (event) => {
        setSearchTerm(event.target.value);
    }

    const handleSubmit = (event) => {
        event.preventDefault();
        fetch(`${url}?q=${searchTerm}&limit=5&appid=${Weather_API_key}&units=metric`)
            .then(response => response.json())
            .then(data => {
                console.log(data);
                setCityArray(data);
            });
    }

    return (
        <div className="container p-3 bg-success">
            <i className='text-danger fw-bold'>Search component</i>
            <form onSubmit={handleSubmit} className='my-3 row g-3'>
                <label className="col-sm-4 col-form-label">
                    Please enter city name:
                </label>
                <div className="col-sm-4">
                    <input type="text" value={searchTerm}
                        onChange={handleChange} className="form-control" />
                </div>
                <div className="col-sm-4">
                    <input type="submit" value="Search" className="btn btn-primary mb-3" />
                </div>
            </form>
            {/* 把onCitySelect传递给Select */}
            <Select cityArray={cityArray} onCitySelect={props.onCitySelect} />
        </div>
    );
}

修改后的Select.js

function Select(props) {
    const [selectedIndex, setSelectedIndex] = React.useState(''); // 存选中的城市索引

    const handleChange = (event) => {
        setSelectedIndex(event.target.value);
    }

    const handleSubmit = (event) => {
        event.preventDefault();
        if (selectedIndex !== '') {
            // 根据索引拿到完整的城市对象
            const selectedCity = props.cityArray[selectedIndex];
            // 调用父组件传递的回调,把城市对象传给Main
            props.onCitySelect(selectedCity);
        }
    }

    return (
        <div className="container p-3 bg-warning">
            <i className='text-danger fw-bold'>Select component</i>
            <form onSubmit={handleSubmit} className=' row g-3'>
                <label className="col-sm col-form-label">
                    Choose your country:</label>
                <select value={selectedIndex} onChange={handleChange}
                    className='form-select col-md'>
                    {/* 用索引作为option的value,方便后续获取完整对象 */}
                    {props.cityArray.map((city, index) =>
                        <option key={index} value={index}>
                            {city.name}, {city.country}
                        </option>
                    )}
                </select>
                <div className="col-sm col-form-label">
                    <input type="submit" value="Submit" className="btn btn-primary mb-3" />
                </div>
            </form>

            {props.cityArray[selectedIndex] && (
                <div> You selected {props.cityArray[selectedIndex].name}, {props.cityArray[selectedIndex].country} </div>
            )}
        </div>
    );
}

关键修改说明

  1. 状态传递路径:通过props将Main的setCityObj以onCitySelect为名逐层传递到Select,让最底层的子组件能直接触发顶层状态更新。
  2. 传递完整对象:Select不再存储字符串形式的城市信息,而是存储城市在数组中的索引,提交时获取完整的城市对象传给Main,确保Body组件能直接使用城市的经纬度等所有字段。
  3. 清理冗余状态:移除Search组件中无用的cel和selectedCity状态,简化组件逻辑。

内容的提问来源于stack exchange,提问作者Adam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:15:23