我目前正在开发一个简单的天气应用程序,使用openwea热处理API。该应用程序用于从两个端点获取数据:一个返回城市当前的天气,另一个返回未来5天的天气预报。应用程序还应该在60秒后触发一个重新获取数据的事件。这就是我试图构建我的解决方案的方式:
在App.js中,我获取数据,然后将其作为道具传递给另外两个组件,一个组件处理当前天气,另一个组件用于天气预报。在CurrentWeatherForecast组件中,我还启动了使用钩子每秒更新状态的函数。当计时器达到60秒时,我将调用"handleRefresh“函数,该函数是作为App.js的道具传递下来的。(在App.js中,实际更新是在哪里进行的)。"handleRefresh“函数位于App.js的呈现方法之外,它更新了一个"step”变量,该变量将导致组件重新呈现并重新获取数据。问题是,在调用setState时,函数会导致无限循环,但我不明白为什么,因为函数在render方法之外。我会在下面贴出我的代码。
import React, { Component } from "react";
import { CurrentWeatherForecast } from "./components/CurrentWeatherForecast";
import { NextDaysWeatherForecast } from "./components/NextDaysWeatherForecast";
export class App extends Component {
constructor(props) {
super(props);
this.state = {
currentWeather: [],
nextDaysWeather: [],
step: 0,
};
}
componentDidMount() {
const { step } = this.state;
var currentWeather;
var nextDaysWeather; // step is used to indicate wether I want to fetch data or not
if (step === 0) {
fetch(
"https://api.openweathermap.org/data/2.5/weather?q=London&appid=1fc71092a81b329e8ce0e1ae88ef0fb7"
)
.then((response) => {
const contentType = response.headers.get("content-type");
if (
!contentType ||
!contentType.includes("application/json")
) {
throw new TypeError("No JSON data!");
}
return response.json();
})
.then((data) => {
currentWeather = data;
})
.catch((error) => console.error(error));
fetch(
"https://api.openweathermap.org/data/2.5/forecast?q=London&appid=1fc71092a81b329e8ce0e1ae88ef0fb7"
)
.then((response) => {
const contentType = response.headers.get("content-type");
if (
!contentType ||
!contentType.includes("application/json")
) {
throw new TypeError("No JSON data!");
}
return response.json();
})
.then((data) => {
let requiredData = data.list.slice(0, 5);
nextDaysWeather = requiredData;
})
.catch((error) => console.error(error));
let f = setTimeout(() => {
this.setState({
currentWeather: currentWeather,
nextDaysWeather: nextDaysWeather,
step: 1, // updating step to 1 after fetching the data
});
}, 1000);
}
}
handleRefresh = () => {
const { step } = this.state;
console.log(step);
this.setState({ step: 0 }); // updating the step to 0 this causes the infinite loop
};
render() {
const { currentWeather, nextDaysWeather } = this.state;
return (
<div>
<CurrentWeatherForecast
currentWeather={currentWeather}
handleRefresh={this.handleRefresh}
/>
<NextDaysWeatherForecast nextDaysWeather={nextDaysWeather} />
</div>
);
}
}
export default App;这在App.js中是忽略NextDaysWeatherForecast组件的,因为它现在是空的。
import React, { useEffect, useState } from "react";
export const CurrentWeatherForecast = (props) => {
const { currentWeather } = props;
const [progressValue, setValue] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setValue((progressValue) =>
progressValue < 61 ? progressValue + 1 : (progressValue = 0)
);
}, 1000);
return () => clearInterval(interval);
}, []);
if (progressValue === 60) {
props.handleRefresh(); // calling the handleRefresh function passed from App.js
}
return (
<div>
<label htmlFor="file">Downloading progress:</label>
<progress id="file" value={progressValue} max="60">
{progressValue}%
</progress>
</div>
);
};这是NextWeatherForecast组件,我在这里启动计时器,然后调用作为支柱传递的"handleRefresh“函数。
谢谢,伙计们!
发布于 2020-09-17 10:45:33
看看这个效果阶段和渲染阶段代码,并尝试猜测什么是错误的。
useEffect(() => {
const interval = setInterval(() => {
setValue((progressValue) =>
progressValue < 61 ? progressValue + 1 : (progressValue = 0)
);
}, 1000);
return () => clearInterval(interval);
}, []);
if (progressValue === 60) {
props.handleRefresh(); // calling the handleRefresh function passed from App.js
}这个函数闻起来特别像溢出:在呈现阶段调用一个导致重发的函数(我们知道handleRefresh会导致重发器)。
if (progressValue === 60) {
props.handleRefresh(); // calling the handleRefresh function passed from App.js
}现在,让我们来看看应该阻止溢出的东西(也就是说,它尝试将progressValue设置为60以外的东西,一旦它设置为60)。
下面是:
progressValue < 61 ? progressValue + 1 : (progressValue = 0)除了,这只会每1000毫秒点燃一次。这意味着您的组件在重发循环中停留了整整一秒钟。一旦将其设置为60,React就会像疯了一样开始呈现,并且在很短的时间内就会超过呈现限制,而progressValue离被设置为0还有很多毫秒的距离。
一个示例解决方案是检查另一个效果中的progressValue === 60。
export const CurrentWeatherForecast = (props) => {
const { currentWeather } = props;
const [progressValue, setValue] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setValue(prevProgressValue => prevProgressValue === 60 ? 0 : prevProgressValue + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
useEffect(() => progressValue === 60 && props.handleRefresh(), [progressValue]);
return (
<div>
<label htmlFor="file">Downloading progress:</label>
<progress id="file" value={progressValue} max="60">
{progressValue}%
</progress>
</div>
);
};发布于 2020-09-17 11:05:18
试试这个:
import React, { useEffect, useState } from "react";
export const CurrentWeatherForecast = ({ currentWeather }) => {
useEffect(() => {
const interval = setInterval(() => {
props.handleRefresh();
}, 60000);
return () => clearInterval(interval);
}, []);
return (
<div>
your codes goes here...
</div>
);
};https://stackoverflow.com/questions/63935451
复制相似问题