如何在React Redux中从OpenWeather API提取当日逐小时天气数据
嘿,这个问题我刚好碰到过,咱们一步步来解决它~
解决方案:分离OpenWeather当日逐小时预报数据
核心思路是通过日期匹配筛选出当日的预报条目——API返回的每个list项里都带了dt_txt字段(格式如2018-10-22 03:00:00),我们可以用这个字段做日期比对,下面给你两种实用方案:
方案一:在Redux Saga中提前过滤数据
如果希望存入Redux的直接就是当日数据,不需要保留完整5天预报,可以在Saga获取响应后直接处理:
修改你的fetchWeatherSaga代码:
function* fetchWeatherSaga(){ try { const weatherResponse = yield fetch("https://samples.openweathermap.org/data/2.5/forecast?lat=35&lon=139&appid=439d4b804bc8187953eb36d2a8c26a02") const weatherData = yield weatherResponse.json(); // 获取当前日期(格式统一为YYYY-MM-DD) const today = new Date().toISOString().split('T')[0]; // 筛选出当日的所有逐小时预报 const todayWeatherList = weatherData.list.filter(item => { const itemDate = item.dt_txt.split(' ')[0]; return itemDate === today; }); // 将处理后的数据存入Redux yield put(fetchWeatherSuccess({ ...weatherData, list: todayWeatherList })); } catch (error) { yield put(fetchWeatherError(error.message)); } }
这样Reducer里的weatherlist对应的list字段就只有当日数据,组件直接取用即可。
方案二:使用Redux Selector(推荐)
如果需要保留完整5天数据(比如后续可能用到),用Selector在组件层面筛选是更优选择——这也是Redux最佳实践,结合reselect库还能缓存计算结果,避免重复渲染。
步骤1:安装reselect(可选但推荐)
npm install reselect # 或者用yarn yarn add reselect
步骤2:创建筛选用的Selector
新建一个selectors.js文件:
import { createSelector } from 'reselect'; // 基础Selector:获取Redux中完整的天气数据 const selectWeatherData = state => state.weather.weatherlist; // 派生Selector:筛选出当日的逐小时预报 export const selectTodayWeatherList = createSelector( [selectWeatherData], (weatherData) => { if (!weatherData?.list) return []; const today = new Date().toISOString().split('T')[0]; return weatherData.list.filter(item => { const itemDate = item.dt_txt.split(' ')[0]; return itemDate === today; }); } );
步骤3:在组件中使用Selector
修改你的WeatherPage组件,通过useSelector获取筛选后的数据:
import { useSelector } from 'react-redux'; import { selectTodayWeatherList } from './path/to/selectors'; export const WeatherPage = ({ fetchWeatherListStart}) => { useEffect(() => { fetchWeatherListStart(); }, [fetchWeatherListStart]); // 获取当日逐小时预报数据 const todayWeather = useSelector(selectTodayWeatherList); // 绑定到UI上展示 return ( <div className="weather-container"> {todayWeather.map(item => ( <div key={item.dt} className="hourly-weather"> <p>时间:{item.dt_txt}</p> <p>温度:{item.main.temp}°C</p> <p>天气:{item.weather[0].description}</p> </div> ))} </div> ); };
两种方案对比
- 方案一:优点是Redux存储的数据量更小,组件无需额外处理;缺点是如果后续需要用到5天完整数据,就得重新请求或修改逻辑。
- 方案二:优点是保留了完整数据,灵活性更高,Selector的缓存机制能提升性能;缺点是需要额外引入reselect(即使不用reselect,自己写普通Selector也可以,只是没有缓存功能)。
我个人更推荐方案二,它更贴合Redux的设计理念,也能应对后续的需求变化~
内容的提问来源于stack exchange,提问作者NewTech Lover
相关产品推荐
相关产品推荐

