Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript setState会导致无限循环,即使它在渲染函数之外_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript setState会导致无限循环,即使它在渲染函数之外

Javascript setState会导致无限循环,即使它在渲染函数之外,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我目前正在使用OpenWeatherAppAPI开发一个简单的天气应用程序。开发该应用程序是为了从两个端点获取数据:一个端点返回您所在城市的当前天气,另一个端点返回未来5天的天气预报。应用程序还应该在60秒后触发一个事件,重新获取数据。这就是我试图构建解决方案的方式: 在App.js中,我获取数据,然后将其作为道具传递给另外两个组件,一个处理当前天气,另一个处理天气预报。在CurrentWeatherForecast组件中,我还启动了使用挂钩每秒更新状态的功能。当计时器达到60秒时,我正在调用“

我目前正在使用OpenWeatherAppAPI开发一个简单的天气应用程序。开发该应用程序是为了从两个端点获取数据:一个端点返回您所在城市的当前天气,另一个端点返回未来5天的天气预报。应用程序还应该在60秒后触发一个事件,重新获取数据。这就是我试图构建解决方案的方式:

在App.js中,我获取数据,然后将其作为道具传递给另外两个组件,一个处理当前天气,另一个处理天气预报。在CurrentWeatherForecast组件中,我还启动了使用挂钩每秒更新状态的功能。当计时器达到60秒时,我正在调用“handleRefresh”函数,该函数是我从App.js作为道具传递下来的。(实际更新发生在App.js中)。“handleRefresh”函数不在App.js的render方法中,它会更新一个“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;
import React,{Component}来自“React”;
从“/components/CurrentWeatherForecast”导入{CurrentWeatherForecast}”;
从“/components/nextdaysheatherforecast”导入{nextdaysheatherforecast}”;
导出类应用程序扩展组件{
建造师(道具){
超级(道具);
此.state={
当前天气:[],
下一天:【】,
步骤:0,
};
}
componentDidMount(){
const{step}=this.state;
天气变化;
var nextdayseagher;//步骤用于指示是否要获取数据
如果(步骤==0){
取回(
"https://api.openweathermap.org/data/2.5/weather?q=London&appid=1fc71092a81b329e8ce0e1ae88ef0fb7"
)
。然后((响应)=>{
const contentType=response.headers.get(“内容类型”);
如果(
!contentType||
!contentType.includes(“应用程序/json”)
) {
抛出新的TypeError(“没有JSON数据!”);
}
返回response.json();
})
。然后((数据)=>{
当前天气=数据;
})
.catch((错误)=>console.error(错误));
取回(
"https://api.openweathermap.org/data/2.5/forecast?q=London&appid=1fc71092a81b329e8ce0e1ae88ef0fb7"
)
。然后((响应)=>{
const contentType=response.headers.get(“内容类型”);
如果(
!contentType||
!contentType.includes(“应用程序/json”)
) {
抛出新的TypeError(“没有JSON数据!”);
}
返回response.json();
})
。然后((数据)=>{
让requiredData=data.list.slice(0,5);
nextDaysWeather=所需数据;
})
.catch((错误)=>console.error(错误));
设f=setTimeout(()=>{
这是我的国家({
currentWeather:currentWeather,
下一天出汗:下一天出汗,
步骤:1,//获取数据后将步骤更新为1
});
}, 1000);
}
}
handleRefresh=()=>{
const{step}=this.state;
控制台日志(步骤);
this.setState({step:0});//将步骤更新为0会导致无限循环
};
render(){
const{currentWeather,nextDaysWeather}=this.state;
返回(
);
}
}
导出默认应用程序;
这是在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>
);
};
import React,{useffect,useState}来自“React”;
导出常数CurrentWeatherForecast=(道具)=>{
const{currentWeather}=道具;
const[progressValue,setValue]=useState(0);
useffect(()=>{
常量间隔=设置间隔(()=>{
设置值((进程值)=>
progressValue<61?progressValue+1:(progressValue=0)
);
}, 1000);
return()=>clearInterval(interval);
}, []);
如果(progressValue==60){
props.handleRefresh();//调用从App.js传递的handleRefresh函数
}
返回(
下载进度:
{progressValue}%
);
};
这是第二个预演组件,我在其中启动计时器,然后调用“handleRefresh”函数,我把它作为道具传递下来


提前谢谢各位

查看此效果阶段和渲染阶段代码,并尝试猜出错误

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
}

现在,让我们寻找一种可以阻止溢出的方法(即,它尝试将
progressValue
设置为60以外的值,一旦设置为60)

这是:

progressValue < 61 ? progressValue + 1 : (progressValue = 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
}

现在,让我们寻找一种可以阻止溢出的方法(即,它尝试将
progressValue
设置为60以外的值,一旦设置为60)

这是:

progressValue < 61 ? progressValue + 1 : (progressValue = 0)
试试这个:

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>
);
};
import React,{useffect,useState}来自“React”;
导出常数CurrentWeatherForecast=({currentWeather})=>{
useffect(()=>{
常量间隔=设置间隔(()=>{
props.handleRefresh();
}, 60000);
return()=>clearInterval(interval);
}, []);
返回(
你的密码在这里。。。
);
};
试试这个:

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>
);
};
import React,{useffect,useState}来自“React”;
导出常数CurrentWeatherForecast=({currentWeather})=>{
useffect(()=>{
常量间隔=设置间隔(()=>{
props.handleRefresh();
}, 60000);
return()=>clearInt