React状态提升问题:子组件无法正确更新父组件cityObj状态
问题解决:React父子组件状态传递异常修复
核心错误点梳理
你的代码存在3个关键问题,直接导致cityObj状态要么undefined要么显示[object object]:
父组件传递错误的状态更新函数
Search组件给Select传参时写了setCityObj={cityObj},这是把cityObj的状态值传了过去,而非更新状态的setCityObj函数,子组件调用时自然无法修改父组件的cityObj。子组件props接收方式错误
React组件的props是唯一入参,不能拆成两个参数接收。你写的function Select(props, {cityObj, setCityObj})不符合规范,所有props需从第一个参数中解构或通过props.xxx访问。提交函数未执行+状态类型不匹配
- 点击Submit时仅引用了
handleSubmit函数,未执行,导致状态更新逻辑根本没触发; - 你通过拼接字符串传递城市信息,若想传递完整城市对象,需直接获取API返回的city对象,而非转成字符串,否则直接打印对象会显示
[object object]。
修正后的代码
Search组件
function Search(props) { const [searchTerm, setSearchTerm] = React.useState(''); const [cityArray, setCityArray] = React.useState([]); const [cel, setCel] = React.useState(null); const [cityObj, setCityObj] = React.useState(null); // 初始值设为null,匹配对象类型 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) => { console.log('The form submitted with input: ' + searchTerm); setCel(() => (searchTerm - 32) / 1.8); 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> {/* 修正:传递状态更新函数setCityObj */} <Select cityArray={cityArray} cityObj={cityObj} setCityObj={setCityObj}/> <Body /> </div> ); }
Select组件
// 修正:从第一个参数解构所有需要的props function Select({ cityArray, cityObj, setCityObj }) { const [selectedCity, setSelectedCity] = React.useState(null); // 直接存储城市对象 const handleChange = (event) => { // 根据选中项的索引获取对应的城市对象 const selectedIndex = event.target.selectedIndex; const targetCity = cityArray[selectedIndex]; setSelectedCity(targetCity); console.log("选中的城市对象:", targetCity); } const handleSubmit = (event) => { event.preventDefault(); console.log('提交的城市:', selectedCity); // 将完整城市对象传递给父组件的cityObj状态 setCityObj(selectedCity); } return ( <div className="container p-3 bg-warning"> <i className='text-danger fw-bold'>Select component</i> <form className='row g-3'> <label className="col-sm col-form-label"> Choose your country:</label> <select onChange={handleChange} className='form-select col-md'> {cityArray.map((city, index) => <option key={city.name + index}> {city.name}, {city.country} </option> )} </select> <div className="col-sm col-form-label"> {/* 修正:执行handleSubmit函数 */} <a onClick={handleSubmit} href="#">Submit</a> </div> </form> {selectedCity && ( <div> You selected {selectedCity.name}, {selectedCity.country} </div> )} {/* 验证父组件是否接收到状态 */} {cityObj && ( <div>父组件已接收城市:{cityObj.name}, {cityObj.country}</div> )} </div> ); }
关键说明
- 父子组件通信规范:父组件必须传递状态更新函数给子组件,子组件通过调用该函数修改父组件状态,这是React父子组件通信的标准方式。
- props接收规范:React组件的所有props都包含在第一个参数中,可通过对象解构或
props.xxx访问。 - 对象状态处理:若需传递完整对象,直接操作API返回的原始对象即可,避免转成字符串导致的
[object object]问题。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

