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

React组件按钮需双击切换周度数据的问题求助

React WeeklyForecast组件按钮双击才生效问题排查

问题现象

开发WeeklyForecast组件时,点击切换按钮(上一页/下一页)需要双击才能生效,首次点击无法更新selectedDayIndex的值。控制台显示首次点击时selectedDayIndex仍为初始值1,第二次点击才会变化。

问题原因

  1. React的setState是异步操作,调用setSelectedDayIndex后立刻使用selectedDayIndex的值进行判断和状态更新,此时获取到的还是更新前的旧值,导致selectedWeek无法同步更新
  2. days变量用var声明并手动修改,不属于React状态,组件重新渲染时会被重置为初始值Object.keys(data.current),无法和状态同步

解决方案

优化思路

  • 使用setState的函数式更新,确保获取最新状态值
  • 将days改为基于状态的计算属性,无需手动维护
  • 同步更新关联状态,避免异步操作导致的逻辑错误

修改后的完整代码

function WeeklyForecast({ data }) {
  const [selectedDayIndex, setSelectedDayIndex] = useState(1);
  const [selectedWeek, setSelectedWeek] = useState("current");

  if (!data) {
    return <div>Loading...</div>;
  }

  // 基于selectedWeek自动计算days,无需手动修改
  const days = Object.keys(data[selectedWeek]);

  const prevClick = () => {
    setSelectedDayIndex(prevIndex => {
      const newIndex = prevIndex > 0 ? prevIndex - 1 : prevIndex;
      // 根据新索引同步更新selectedWeek
      let newWeek = "current";
      switch (newIndex) {
        case 0:
          newWeek = "previous";
          break;
        case 1:
          newWeek = "current";
          break;
        case 2:
          newWeek = "next";
          break;
        default:
          break;
      }
      setSelectedWeek(newWeek);
      console.log(newIndex);
      return newIndex;
    });
  };

  const nextClick = () => {
    setSelectedDayIndex(prevIndex => {
      const maxIndex = Object.keys(data).length - 1;
      const newIndex = prevIndex < maxIndex ? prevIndex + 1 : prevIndex;
      // 根据新索引同步更新selectedWeek
      let newWeek = "current";
      switch (newIndex) {
        case 0:
          newWeek = "previous";
          break;
        case 1:
          newWeek = "current";
          break;
        case 2:
          newWeek = "next";
          break;
        default:
          break;
      }
      setSelectedWeek(newWeek);
      console.log(newIndex);
      return newIndex;
    });
  };

  return (
    <div className='WeeklyForecast'>
      <div className="Prev-Btn">
        <button onClick={prevClick}>&lt;</button>
      </div>
      <div className="Forecast-List">
        {days.map((day, index) => (
          <div key={index}>
            <p>{day}</p>
            <p>{data[selectedWeek][day].type}</p>
            <p>{data[selectedWeek][day].degree}°</p>
          </div>
        ))}
      </div>
      <div className="Next-Btn">
        <button onClick={nextClick}>&gt;</button>
      </div>
    </div>
  );
}

export default WeeklyForecast;

关键修改说明

  • 函数式状态更新:通过setSelectedDayIndex(prevIndex => { ... })获取最新的状态值,避免异步更新导致的旧值误用
  • 计算属性替代手动变量:days直接基于selectedWeek计算,组件渲染时自动同步,无需手动维护
  • 同步状态更新:在更新selectedDayIndex的同时,直接根据新索引计算并更新selectedWeek,保证状态一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 02:47:06