React - 多个组件确实更新了 - 为什么?
React - Multiple components did update - why?
作为 React 的新手,我正在尝试了解生命周期挂钩,这种情况是 ComponentDidUpdate()
所以我有一个位置 class 组件 - 它是一个简单的表单,带有供用户输入位置的输入。我的 handleSubmit 事件阻止了新的页面请求,而是更新了这个高阶组件中的状态。
在 location 中,我有一个天气 class 组件,它接收新位置作为 prop,用位置更新它自己的状态,并在 componentDidUpdate() 上触发一个 api 请求,然后它也设置它的解决获取后,说明该位置的天气状况。然后它将状态传递给 jsx div 这样用户就可以看到天气状况。
为此,我可以看到三个 componentDidUpdate() 事件从天气组件输出到控制台 - 我只是在猜测是什么导致了它们。
第一次从更高位置组件接收到新的位置道具时?
第二个将它自己的状态设置到新位置?
第三次,当获取被解析并设置天气状态时?
或者也许一个是当它用天气状况更新 div 时。
你能告诉我这是怎么回事吗,它真的会帮助我构建一个更好的应用程序并调试它。
谢谢,
菲尔
本地组件:
import React, { Component } from "react";
import './local.css';
import Earth from './Earth';
import { Weather } from '../spies/weather/Spy';
class Local extends Component {
constructor() {
super()
this.state = {
location:''
}
}
handleSubmit = e => {
e.preventDefault();
if(e.target.elements.localInput.value) this.setState({ location: e.target.elements.localInput.value })
else return;
}
render() {
return (
<React.Fragment>
<div id="local" >
<form className="appBorder" onSubmit={this.handleSubmit}>
<input id="localInput" className="appInput appBorder" type="text" placeholder="Enter the location">
</input>
<button className="appButton">
<Earth className="earth"/>
</button>
</form>
</div>
<Weather location={this.state.location}/>
</React.Fragment>
)
}
}
export default Local;
天气组件(别名间谍):
import React, { Component } from "react";
import './weather.css';
import '../spy.css';
import { getWeather } from './api';
class Spy extends Component {
constructor() {
super()
this.state = {
location: null,
weatherData: null,
error: '',
};
}
componentDidUpdate(prevProps, prevState) {
console.log("update");
if (prevProps.location !== this.props.location) {
this.setState({location: this.props.location},()=>{
getWeather(this.state.location)
.then(data => {
console.log("api request resolved");
this.setState({ weatherData: data });
})
.catch(error =>
this.setState({ error: error.message }));
}
)}
else return;
}
render() {
return (
<div id="spyWeather" className="appBorder spy">
<h3 className="spyName">Weather for {this.state.location}</h3>
<p id="weatherDesc" className="spyData">Conditions: {this.state.weatherData ? this.state.weatherData.current.weather_descriptions : ""}</p>
<p id="weatherTemp" className="spyData">Temperature: {this.state.weatherData ? this.state.weatherData.current.temperature : ""} °C</p>
<p id="weatherHumid" className="spyData">Humidity: {this.state.weatherData ? this.state.weatherData.current.humidity : ""} %</p>
<p id="weatherPrecip" className="spyData">Precipitation: {this.state.weatherData ? this.state.weatherData.current.precip : ""} mm</p>
</div>
)
}
}
export { Spy as Weather };
控制台(2 次更新,api 触发然后另一个更新):-
[HMR] Waiting for update signal from WDS...
2 Spy.js:18 update
Spy.js:23 api request resolved
Spy.js:18 update
给定
componentDidUpdate(prevProps, prevState) {
console.log("update");
if (prevProps.location !== this.props.location) {
this.setState({location: this.props.location},()=>{
getWeather(this.state.location)
.then(data => {
console.log("api request resolved");
this.setState({ weatherData: data });
})
.catch(error =>
this.setState({ error: error.message }));
}
)}
else return;
}
和日志
2 Spy.js:18 update
Spy.js:23 api request resolved
Spy.js:18 update
是的,我看到三个 renders/rerenders。
第一个“更新”是从 props.location
从 null
变为 一些 值。条件测试 prevProps.location !== this.props.location
解析 true
,因此采用快乐路径并使用位置更新状态。
第二次“更新”现在是因为状态更新为 location
。
在上一次状态更新的同时,调用了 setState
回调并获取了天气信息。在承诺链的快乐路径中是日志“api 请求已解决”和另一个 setState
.
第三次“更新”再次来自状态更新,这次是weatherData
。
如你所知,在本地状态中存储道具是反应中的反模式,只需发出你的副作用,比如在道具改变时获取天气。也不建议在 setState
回调中链接状态更新,因为每个嵌套状态更新都会延迟 that 更新 1(或更多)渲染周期,并且会使调试更加困难。最好在 componentDidUpdate
中简单地处理它们。也不需要“void”return,因为所有 JS 函数都有一个隐式 return,不需要 return 任何 actual值。
componentDidUpdate(prevProps, prevState) {
console.log("update");
if (prevProps.location !== this.props.location) {
if (location) {
// location prop changed and is truthy, get weather
getWeather(this.state.location)
.then(data => {
console.log("api request resolved");
this.setState({ weatherData: data });
})
.catch(error => this.setState({ error: error.message }));
}
}
}
这应该刻画出那些最初“浪费的”渲染周期之一,日志现在应该是
Spy.js:18 update
Spy.js:23 api request resolved
Spy.js:18 update
作为 React 的新手,我正在尝试了解生命周期挂钩,这种情况是 ComponentDidUpdate()
所以我有一个位置 class 组件 - 它是一个简单的表单,带有供用户输入位置的输入。我的 handleSubmit 事件阻止了新的页面请求,而是更新了这个高阶组件中的状态。
在 location 中,我有一个天气 class 组件,它接收新位置作为 prop,用位置更新它自己的状态,并在 componentDidUpdate() 上触发一个 api 请求,然后它也设置它的解决获取后,说明该位置的天气状况。然后它将状态传递给 jsx div 这样用户就可以看到天气状况。
为此,我可以看到三个 componentDidUpdate() 事件从天气组件输出到控制台 - 我只是在猜测是什么导致了它们。
第一次从更高位置组件接收到新的位置道具时?
第二个将它自己的状态设置到新位置?
第三次,当获取被解析并设置天气状态时?
或者也许一个是当它用天气状况更新 div 时。
你能告诉我这是怎么回事吗,它真的会帮助我构建一个更好的应用程序并调试它。
谢谢,
菲尔
本地组件:
import React, { Component } from "react";
import './local.css';
import Earth from './Earth';
import { Weather } from '../spies/weather/Spy';
class Local extends Component {
constructor() {
super()
this.state = {
location:''
}
}
handleSubmit = e => {
e.preventDefault();
if(e.target.elements.localInput.value) this.setState({ location: e.target.elements.localInput.value })
else return;
}
render() {
return (
<React.Fragment>
<div id="local" >
<form className="appBorder" onSubmit={this.handleSubmit}>
<input id="localInput" className="appInput appBorder" type="text" placeholder="Enter the location">
</input>
<button className="appButton">
<Earth className="earth"/>
</button>
</form>
</div>
<Weather location={this.state.location}/>
</React.Fragment>
)
}
}
export default Local;
天气组件(别名间谍):
import React, { Component } from "react";
import './weather.css';
import '../spy.css';
import { getWeather } from './api';
class Spy extends Component {
constructor() {
super()
this.state = {
location: null,
weatherData: null,
error: '',
};
}
componentDidUpdate(prevProps, prevState) {
console.log("update");
if (prevProps.location !== this.props.location) {
this.setState({location: this.props.location},()=>{
getWeather(this.state.location)
.then(data => {
console.log("api request resolved");
this.setState({ weatherData: data });
})
.catch(error =>
this.setState({ error: error.message }));
}
)}
else return;
}
render() {
return (
<div id="spyWeather" className="appBorder spy">
<h3 className="spyName">Weather for {this.state.location}</h3>
<p id="weatherDesc" className="spyData">Conditions: {this.state.weatherData ? this.state.weatherData.current.weather_descriptions : ""}</p>
<p id="weatherTemp" className="spyData">Temperature: {this.state.weatherData ? this.state.weatherData.current.temperature : ""} °C</p>
<p id="weatherHumid" className="spyData">Humidity: {this.state.weatherData ? this.state.weatherData.current.humidity : ""} %</p>
<p id="weatherPrecip" className="spyData">Precipitation: {this.state.weatherData ? this.state.weatherData.current.precip : ""} mm</p>
</div>
)
}
}
export { Spy as Weather };
控制台(2 次更新,api 触发然后另一个更新):-
[HMR] Waiting for update signal from WDS...
2 Spy.js:18 update
Spy.js:23 api request resolved
Spy.js:18 update
给定
componentDidUpdate(prevProps, prevState) {
console.log("update");
if (prevProps.location !== this.props.location) {
this.setState({location: this.props.location},()=>{
getWeather(this.state.location)
.then(data => {
console.log("api request resolved");
this.setState({ weatherData: data });
})
.catch(error =>
this.setState({ error: error.message }));
}
)}
else return;
}
和日志
2 Spy.js:18 update
Spy.js:23 api request resolved
Spy.js:18 update
是的,我看到三个 renders/rerenders。
第一个“更新”是从
props.location
从null
变为 一些 值。条件测试prevProps.location !== this.props.location
解析true
,因此采用快乐路径并使用位置更新状态。第二次“更新”现在是因为状态更新为
location
。 在上一次状态更新的同时,调用了setState
回调并获取了天气信息。在承诺链的快乐路径中是日志“api 请求已解决”和另一个setState
.第三次“更新”再次来自状态更新,这次是
weatherData
。
如你所知,在本地状态中存储道具是反应中的反模式,只需发出你的副作用,比如在道具改变时获取天气。也不建议在 setState
回调中链接状态更新,因为每个嵌套状态更新都会延迟 that 更新 1(或更多)渲染周期,并且会使调试更加困难。最好在 componentDidUpdate
中简单地处理它们。也不需要“void”return,因为所有 JS 函数都有一个隐式 return,不需要 return 任何 actual值。
componentDidUpdate(prevProps, prevState) {
console.log("update");
if (prevProps.location !== this.props.location) {
if (location) {
// location prop changed and is truthy, get weather
getWeather(this.state.location)
.then(data => {
console.log("api request resolved");
this.setState({ weatherData: data });
})
.catch(error => this.setState({ error: error.message }));
}
}
}
这应该刻画出那些最初“浪费的”渲染周期之一,日志现在应该是
Spy.js:18 update
Spy.js:23 api request resolved
Spy.js:18 update