Javascript 合并反应状态的意外结果

Javascript 合并反应状态的意外结果,javascript,reactjs,Javascript,Reactjs,一旦找到天气并显示出来,点击摄氏度应该运行一个unitHandler,然后转换温度值,然后更新状态。但是,当更新this.state.currentWeather.temp(一个已经存在的属性,所以我认为它会进行“浅层”合并,只“更新”状态)时,它会清除当前存在的其他状态属性 我想知道为什么它没有像React文档显示的那样进行“浅层”合并,而是清除我的其他状态?是否因为React有时会批量处理多个setState()性能调用,如以下文档所示 状态更新可能是异步的,可能会批处理多个setState

一旦找到天气并显示出来,点击摄氏度应该运行一个
unitHandler
,然后转换温度值,然后更新状态。但是,当更新
this.state.currentWeather.temp
(一个已经存在的属性,所以我认为它会进行“浅层”合并,只“更新”状态)时,它会清除当前存在的其他状态属性

我想知道为什么它没有像React文档显示的那样进行“浅层”合并,而是清除我的其他状态?是否因为React有时会批量处理多个
setState()
性能调用,如以下文档所示

状态更新可能是异步的,可能会批处理多个setState() 调用单个更新以提高性能

由于this.props和this.state可能会异步更新,因此 不应依赖其值来计算下一个状态

我想我只是感到困惑,因为就在文档的下面,它说在更新/合并时,它会保持其他状态不变:

当调用setState()时,状态更新被合并,React合并 将提供的对象转换为当前状态。合并很浅,所以 this.setState({comments})使this.state.posts保持不变,但是 完全替换此.state.comments

做一些研究,我认为我可以防止这种情况的一种方法是将
prevState
函数传递到
this.setState
,但是,我无法使用扩展运算符正确编写函数

constroot=document.querySelector('.root');
类应用程序扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
单位:'',
当前天气:{
主要内容:“,
描述:'',
临时工:'',
}
}
this.getWeather=this.getWeather.bind(this);
this.unitHandler=this.unitHandler.bind(this);
}
天气预报(东){
e、 预防默认值();
const city=e.target.elements.city.value;
const country=e.target.elements.country.value;
常量appID='bf6cdb2b4f3c1293c29610bd1d54512b';
const currentWeatherURL=`https://api.openweathermap.org/data/2.5/weather?q=${city}、${country}&units=imperial&APPID=${APPID}`;
常数预报器URL=`https://api.openweathermap.org/data/2.5/forecast?q=${city}、${country}&units=imperial&APPID=${APPID}`;
//仅获取当前天气数据
获取(currentWeatherURL)
.then((response)=>response.json())
。然后((数据)=>{
这是我的国家({
单位:华氏度,
当前天气:{
main:data.weather[0]。main,
desc:data.weather[0]。说明,
温度:data.main.temp,
}
});
})
.catch(()=>{console.log('发生了错误,但我们发现了错误'));
}
单位处理程序(e){
函数转换器Tocelsius(华氏度){
返回((华氏32度)*5/9)
}
函数转换为华氏温度(摄氏度){
返回((摄氏度*9/5)+32)
}
//如果检查华氏温度
如果(e.target.value==='fahrenheit'){
恒温器华氏温度=转换华氏温度(本状态当前天气温度);
这个.setState({单位:'F',当前天气:{温度:华氏度}});
} 
//否则,将选中摄氏度
否则{
const celsiusTemp=convertToCelsius(this.state.currentWeather.temp);
这个.setState({单位:'°C',当前天气:{temp:celsiusTemp}});
}
}
render(){
log('handler state');
console.log(this.state);
返回(
)
}
}
//输入城市和州的组件
功能位置输入(道具){
返回(
搜索
)
}
//用于转换所有单位的组件(华氏摄氏度)
功能单元转换器(props){
返回(
华氏的
摄氏度
)
}
//基本天气组件(为每周预报制作专门组件的意图)
功能天气(道具){
log(“组件状态”);
控制台日志(道具);
常量图标={
雷暴:,
毛毛雨:,
雨:,
雪:,
清楚:,
大气:“没有可用的图标”,
云:,
};
让currentIcon=icons[props.weatherStats.main.toLowerCase()];
返回(
{props.location}
{props.day}
{currentIcon}
{props.weatherStats.main}
{props.weatherStats.desc}
{props.weatherStats.temp&{Math.round(props.weatherStats.temp)}{props.unit}
) 
}
//使用React的专门化概念从基础创建更具体的天气组件
功能当前天气(道具){
const dateObj=新日期();
常量天数=[“星期日”、“星期一”、“星期二”、“星期三”、“星期四”、“星期五”];
const currentDay=days[dateObj.getDay()];
返回(
)
}
ReactDOM.render(,root)
.weather应用程序{
文本对齐:居中;
}
·天气气流{
显示:内联块;
}
.wf容器{
显示器:flex;
证明内容:中心;
对齐项目:居中;
}

这是因为您完全替换了当前天气对象。您必须保留其他当前天气属性才能使其正常工作:

this.setState((state) => ({
    unit: '°C',
    currentWeather: {
        ...state.currentWeather,
        temp: celsiusTemp
    }
}));
当然,您必须对其他转换方法执行相同的操作


是工作示例。

这是因为您完全替换了当前天气对象。您必须保留其他当前天气属性才能使其正常工作:

this.setState((state) => ({
    unit: '°C',
    currentWeather: {
        ...state.currentWeather,
        temp: celsiusTemp
    }
}));
当然,您必须对其他转换方法执行相同的操作

是工作示例。

您的setState()应该如下所示:

this.setState(prevState => ({ 
  ...prevState, 
  currentWeather: { ...prevState.currentWeather, temp: celsiusTemp } 
}));
您的setState()应该如下所示:

this.setState(prevState => ({ 
  ...prevState, 
  currentWeather: { ...prevState.currentWeather, temp: celsiusTemp } 
}));
请添加al