API 调用后 ReactJS img 未更新
ReactJS img not updating after API Call
我现在正在学习 React 并试图解决为什么我的其他组件更新了信息但我的 img 标签在第二次 API 调用后没有更新的原因。
这是我的代码:
export default function LandingPage() {
const [zipcode, setZipCode] = useState('');
const [loading, setLoading] = useState(false);
const [weatherData, setWeatherData] = useState();
var [cityWeatherData, setCityWeatherData] = useState([]);
var [forecast, setForcast] = useState([]);
return(
<TextField
label='Zip Code'
value={zipcode}
onChange={(e) => { setZipCode(e.target.value) }} />
<Button
sx={{ ml: 3, backgroundColor: '#5F8FFF', color: 'white', '&:hover': { color: '#5F8FFF' } }}
onClick={ () => {
currentWeather(zipcode, apiKey)
.then( async (result) => {
setLoading(true);
await sevenDayWeather(result['coord']['lon'], result['coord']['lat'], apiKey)
.then( (response) => {
response['daily'].forEach( (day) => {
console.log('day forecast: ', day);
console.log('Day Weather: ', day['weather'][0]['icon']);
setForcast( forecast => [...forecast, day['weather'][0]['icon']]);
})
});
});
}}>
Search
</Button>
{loading ?
// console.log('forecast: ', forecast)
<WeatherBox
apiKey={apiKey}
name={weatherData['name']}
lat={weatherData['coord']['lat']}
lon={weatherData['coord']['lon']}
feelsLike={weatherData['main']['feels_like']}
highestTemp={weatherData['main']['temp_max']}
lowestTemp={weatherData['main']['temp_min']}
forecast={forecast}
/> : <></>}
);}
对于我的 WeatherBox
组件
export default function WeatherBox(props) {
let newDate = new Date()
let date = newDate.getDate();
let month = newDate.getMonth() + 1;
let year = newDate.getFullYear();
return (
<Box
className='retrievedInformation'
sx={{
mt: 10,
p: 5,
boxShadow: 'gray 5px 10px 10px 5px',
borderRadius: '20px',
textAlign: 'end',
backgroundImage: `url(${sunny})`,
objectFit: 'contain',
backgroundRepeat: 'no-repeat',
backgroundSize: '500px 500px'
}}>
<Typography
sx={{ fontSize: '50px' }}>
{props.name}
</Typography>
<Typography
sx={{ fontSize: '25px' }}>
Today: {month} / {date} / {year}
</Typography>
<img src={`http://openweathermap.org/img/wn/${props.forecast[0]}@2x.png`} alt='forecast image' />
<Box
display='flex'
flexDirection='row'
sx={{ textAlign: 'end', justifyContent: 'end', alignItems: 'end' }}>
<Typography
sx={{ mr: 3, fontSize: '30px', fontWeight: '300', color: 'gray' }}>
Feels Like:
</Typography>
<Typography
sx={{ fontSize: '30px' }}>
{props.feelsLike} F
</Typography>
</Box>
<Box
display='flex'
flexDirection='row'
justifyContent='end'
alignItems='end'
sx={{ textAlign: 'end' }}>
<Typography
sx={{ mr: 3, fontSize: '20px', fontWeight: '300', color: 'gray', textAlign: 'end' }}>
Highest Temperature:
</Typography>
<Typography
sx={{ fontSize: '20px', textAlign: 'end' }}>
{props.highestTemp} F
</Typography>
</Box>
<Box
display='flex'
flexDirection='row'
justifyContent='end'
alignItems='end'>
<Typography sx={{ mr: 3, fontSize: '20px', fontWeight: '300', color: 'gray', textAlign: 'end' }}>Lowest Temperature: </Typography>
<Typography sx={{ fontSize: '20px', textAlign: 'end' }}> {props.lowestTemp} F</Typography>
</Box>
<Box textAlign='end' alignItems='end' justifyContent='end'>
<Typography sx={{ mt: 5, fontSize: '30px' }}>Weather forecast for the next 7 days</Typography>
<img src={`http://openweathermap.org/img/wn/${props.forecast[1]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[2]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[3]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[4]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[5]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[6]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[7]}@2x.png`} alt='forecast image' />
</Box>
</Box>
);
}
我的 forecast
数组也已更新并保存所有正确的值,但是 weatherbox
中的 img 标签仍然没有更新
提前感谢您的帮助
编辑:添加 link 到 codesandbox
https://codesandbox.io/s/blissful-thunder-u76vwt?file=/src/App.js
问题
The img tag loads all the images fine for the first call however, the
problem is that when I do another zipcode and clicked search, the
texts updated, but the img tag (the weather images) did not update (
i.e. first search 91001 everything looks great, searched again for
95133, name changed to San Jose but the weather forecast images did
not update from 91001's to 95133's)
您始终将预测数据附加到 forecast
状态,但仅引用前 8 个元素。
response["daily"].forEach((day) => {
setForcast((forecast) => [
...forecast, // <-- shallow copy persists old forecast data
day["weather"][0]["icon"]
]);
});
...
<img
src={`http://openweathermap.org/img/wn/${props.forecast[0]}@2x.png`}
alt="forecast image"
/>
...
<img
src={`http://openweathermap.org/img/wn/${props.forecast[1]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[2]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[3]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[4]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[5]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[6]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[7]}@2x.png`}
alt="forecast image"
/>
解决方案
解决,更新时应该覆盖预测状态。
setForcast(response.daily.map((day) => day.weather[0].icon));
这是一个“优化的”按钮点击处理程序。
<Button
onClick={async () => {
setLoading(false);
const weather = await currentWeather(zipcode, apiKey);
setWeatherData(weather);
console.log(weather);
const forecast = await sevenDayWeather(
weather.coord.lon,
weather.coord.lat,
apiKey
);
setForcast(forecast.daily.map((day) => day.weather[0].icon));
setLoading(true);
}}
>
Search
</Button>
并且为了 DRY-ness,映射预测图像。
{props.forecast.map((id, index) => (
<img
key={index}
src={`http://openweathermap.org/img/wn/${id}@2x.png`}
alt="forecast image"
/>
))}
我现在正在学习 React 并试图解决为什么我的其他组件更新了信息但我的 img 标签在第二次 API 调用后没有更新的原因。
这是我的代码:
export default function LandingPage() {
const [zipcode, setZipCode] = useState('');
const [loading, setLoading] = useState(false);
const [weatherData, setWeatherData] = useState();
var [cityWeatherData, setCityWeatherData] = useState([]);
var [forecast, setForcast] = useState([]);
return(
<TextField
label='Zip Code'
value={zipcode}
onChange={(e) => { setZipCode(e.target.value) }} />
<Button
sx={{ ml: 3, backgroundColor: '#5F8FFF', color: 'white', '&:hover': { color: '#5F8FFF' } }}
onClick={ () => {
currentWeather(zipcode, apiKey)
.then( async (result) => {
setLoading(true);
await sevenDayWeather(result['coord']['lon'], result['coord']['lat'], apiKey)
.then( (response) => {
response['daily'].forEach( (day) => {
console.log('day forecast: ', day);
console.log('Day Weather: ', day['weather'][0]['icon']);
setForcast( forecast => [...forecast, day['weather'][0]['icon']]);
})
});
});
}}>
Search
</Button>
{loading ?
// console.log('forecast: ', forecast)
<WeatherBox
apiKey={apiKey}
name={weatherData['name']}
lat={weatherData['coord']['lat']}
lon={weatherData['coord']['lon']}
feelsLike={weatherData['main']['feels_like']}
highestTemp={weatherData['main']['temp_max']}
lowestTemp={weatherData['main']['temp_min']}
forecast={forecast}
/> : <></>}
);}
对于我的 WeatherBox
组件
export default function WeatherBox(props) {
let newDate = new Date()
let date = newDate.getDate();
let month = newDate.getMonth() + 1;
let year = newDate.getFullYear();
return (
<Box
className='retrievedInformation'
sx={{
mt: 10,
p: 5,
boxShadow: 'gray 5px 10px 10px 5px',
borderRadius: '20px',
textAlign: 'end',
backgroundImage: `url(${sunny})`,
objectFit: 'contain',
backgroundRepeat: 'no-repeat',
backgroundSize: '500px 500px'
}}>
<Typography
sx={{ fontSize: '50px' }}>
{props.name}
</Typography>
<Typography
sx={{ fontSize: '25px' }}>
Today: {month} / {date} / {year}
</Typography>
<img src={`http://openweathermap.org/img/wn/${props.forecast[0]}@2x.png`} alt='forecast image' />
<Box
display='flex'
flexDirection='row'
sx={{ textAlign: 'end', justifyContent: 'end', alignItems: 'end' }}>
<Typography
sx={{ mr: 3, fontSize: '30px', fontWeight: '300', color: 'gray' }}>
Feels Like:
</Typography>
<Typography
sx={{ fontSize: '30px' }}>
{props.feelsLike} F
</Typography>
</Box>
<Box
display='flex'
flexDirection='row'
justifyContent='end'
alignItems='end'
sx={{ textAlign: 'end' }}>
<Typography
sx={{ mr: 3, fontSize: '20px', fontWeight: '300', color: 'gray', textAlign: 'end' }}>
Highest Temperature:
</Typography>
<Typography
sx={{ fontSize: '20px', textAlign: 'end' }}>
{props.highestTemp} F
</Typography>
</Box>
<Box
display='flex'
flexDirection='row'
justifyContent='end'
alignItems='end'>
<Typography sx={{ mr: 3, fontSize: '20px', fontWeight: '300', color: 'gray', textAlign: 'end' }}>Lowest Temperature: </Typography>
<Typography sx={{ fontSize: '20px', textAlign: 'end' }}> {props.lowestTemp} F</Typography>
</Box>
<Box textAlign='end' alignItems='end' justifyContent='end'>
<Typography sx={{ mt: 5, fontSize: '30px' }}>Weather forecast for the next 7 days</Typography>
<img src={`http://openweathermap.org/img/wn/${props.forecast[1]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[2]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[3]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[4]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[5]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[6]}@2x.png`} alt='forecast image' />
<img src={`http://openweathermap.org/img/wn/${props.forecast[7]}@2x.png`} alt='forecast image' />
</Box>
</Box>
);
}
我的 forecast
数组也已更新并保存所有正确的值,但是 weatherbox
中的 img 标签仍然没有更新
提前感谢您的帮助
编辑:添加 link 到 codesandbox
https://codesandbox.io/s/blissful-thunder-u76vwt?file=/src/App.js
问题
The img tag loads all the images fine for the first call however, the problem is that when I do another zipcode and clicked search, the texts updated, but the img tag (the weather images) did not update ( i.e. first search 91001 everything looks great, searched again for 95133, name changed to San Jose but the weather forecast images did not update from 91001's to 95133's)
您始终将预测数据附加到 forecast
状态,但仅引用前 8 个元素。
response["daily"].forEach((day) => {
setForcast((forecast) => [
...forecast, // <-- shallow copy persists old forecast data
day["weather"][0]["icon"]
]);
});
...
<img
src={`http://openweathermap.org/img/wn/${props.forecast[0]}@2x.png`}
alt="forecast image"
/>
...
<img
src={`http://openweathermap.org/img/wn/${props.forecast[1]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[2]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[3]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[4]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[5]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[6]}@2x.png`}
alt="forecast image"
/>
<img
src={`http://openweathermap.org/img/wn/${props.forecast[7]}@2x.png`}
alt="forecast image"
/>
解决方案
解决,更新时应该覆盖预测状态。
setForcast(response.daily.map((day) => day.weather[0].icon));
这是一个“优化的”按钮点击处理程序。
<Button
onClick={async () => {
setLoading(false);
const weather = await currentWeather(zipcode, apiKey);
setWeatherData(weather);
console.log(weather);
const forecast = await sevenDayWeather(
weather.coord.lon,
weather.coord.lat,
apiKey
);
setForcast(forecast.daily.map((day) => day.weather[0].icon));
setLoading(true);
}}
>
Search
</Button>
并且为了 DRY-ness,映射预测图像。
{props.forecast.map((id, index) => (
<img
key={index}
src={`http://openweathermap.org/img/wn/${id}@2x.png`}
alt="forecast image"
/>
))}