You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React组件状态更新异常:父组件数据变更时子组件未同步

问题原因与解决方案

你的推测完全正确——问题出在Tomorrow.jsx的useEffect依赖数组为空,它只会在组件首次挂载时执行一次。当父组件传递的props.tomorrowForcast更新时,这个useEffect不会重新触发,导致本地状态tomorrowForcast始终停留在初始计算结果,没有同步新数据。

修复方案1:修正useEffect依赖项

把props.tomorrowForcast加入useEffect的依赖数组,这样每次props更新时,都会重新计算明日预报数据并更新状态:

const [tomorrowForcast, setTomorrowForcast] = useState([])

useEffect(function () {
  // 先判断props数据是否存在,避免空值报错
  if (!props.tomorrowForcast?.list) return;

  const forcastArray = props.tomorrowForcast.list;
  const today = new Date();
  // 计算明日的日期(处理月末跨月情况,比如今天是31号,直接+1会变成32,用Date对象自动处理)
  const tomorrow = new Date(today);
  tomorrow.setDate(today.getDate() + 1);
  const tomorrowDateStr = tomorrow.toISOString().split('T')[0]; // 格式化为YYYY-MM-DD

  const newTomorrowForecasts = forcastArray.filter(forcast => {
    // 提取预报数据的日期部分
    const forecastDateStr = forcast.dt_txt.split(' ')[0];
    // 直接比对完整日期字符串,避免只比对日数的bug(比如月末31号+1变成32,slice(8)会出错)
    return forecastDateStr === tomorrowDateStr;
  });

  setTomorrowForcast(newTomorrowForecasts);
}, [props.tomorrowForcast]); // 加入依赖项,props变化时重新执行

const forcasts = tomorrowForcast.map(forcast => {
  let tomorrowObj = {...forcast, identifier: 'tomorrow'}
  const get_dt = forcast.dt_txt
  const split_dt = get_dt.split(" ")
  const get_time = split_dt[1]
  const time = get_time.slice(0, 5)
  return (
    <WeatherBlock {...tomorrowObj} d_or_t={time} />
  )
})

优化方案2:移除本地状态,直接在渲染时计算

如果不需要把筛选后的结果存为状态,完全可以直接在渲染阶段计算,彻底避免状态不同步的问题:

// 移除useState和useEffect,直接在渲染时处理
const getTomorrowForecasts = () => {
  if (!props.tomorrowForcast?.list) return [];

  const today = new Date();
  const tomorrow = new Date(today);
  tomorrow.setDate(today.getDate() + 1);
  const tomorrowDateStr = tomorrow.toISOString().split('T')[0];

  return props.tomorrowForcast.list.filter(forcast => {
    const forecastDateStr = forcast.dt_txt.split(' ')[0];
    return forecastDateStr === tomorrowDateStr;
  });
};

const forcasts = getTomorrowForecasts().map(forcast => {
  let tomorrowObj = {...forcast, identifier: 'tomorrow'}
  const get_dt = forcast.dt_txt
  const split_dt = get_dt.split(" ")
  const get_time = split_dt[1]
  const time = get_time.slice(0, 5)
  return (
    <WeatherBlock {...tomorrowObj} d_or_t={time} />
  )
})

额外说明

原代码中的日期判断逻辑有潜在bug:比如今天是当月最后一天(10月31日),date2会变成32,而预报数据中的日期日数最大是31,这时候永远匹配不到。改用Date对象处理日期,可以自动处理跨月情况,确保逻辑正确。

内容的提问来源于stack exchange,提问作者Jack_T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 06:15:47