为什么组件不能正确重新渲染?

问题描述 投票:0回答:1

我的计时器应用程序运行不正常。 我正在尝试编写可以在服务器上保存数据的计时器。 应用逻辑: 当页面第一次呈现时,它从服务器(mockAPI)获取数据以呈现实际时间,并将其传递给子组件。但是组件重新渲染正确只有它的状态更新通过“重置”按钮。我预计在 App 组件中的 useEffect 中的异步函数完成后,将使用新道具重新渲染。但是出了点问题... 为什么?

const link = "https://63fef788571200b7b7d2e115.mockapi.io/Time";

function App() {
  let [hours, setHours] = React.useState(0);
  let [minutes, setMinutes] = React.useState(0);
  let [seconds, setSeconds] = React.useState(0);

  React.useEffect(() => {
    axios
      .get(link)
      .then((res) => res.data[0].time)
      .then((res) => {
        setHours(res.h);
        setMinutes(res.m);
        setSeconds(res.s);
      })
      .catch((error) => {
        console.log(error.message);
      });
  }, [hours, minutes, seconds]);

  return (
    <>
      <CountUp hours={hours} minutes={minutes} seconds={seconds} />
    </>
  );
}

const CountUp = ({ hours, minutes, seconds }) => {
  const [paused, setPaused] = React.useState(true);

  let [[h, m, s], setTime] = React.useState([hours, minutes, seconds]);
  
  const tick = () => {
    
    if (paused) return;

    if (m === 60) {
      setTime([(h += 1), (m = 0), (s = 0)]);
    } else if (s === 60) {
      setTime([h, (m += 1), (s = 0)]);
    } else {
      setTime([h, m, (s += 1)]);
    }
  };

  const reset = () => {
    setTime([parseInt(hours), parseInt(minutes), parseInt(seconds)]);
    setPaused(true);
  };

  const addDateToServer = async () => {
    try {
      await axios.delete(
        `https://63fef788571200b7b7d2e115.mockapi.io/Time/${"1"}`
      );
      await axios.post("https://63fef788571200b7b7d2e115.mockapi.io/Time", {
        time: { h, m, s },
      });
    } catch (error) {
      alert("Не удалось сохранить информацию");
    }
  };

  React.useEffect(() => {
    const timerID = setInterval(() => {
      tick();
    }, 1000);
    return () => clearInterval(timerID);
  }, [paused]);

  return (
    <>
      <h1>Working time</h1>
      <div>
        <p>{`${h.toString().padStart(2, "0")}:${m
          .toString()
          .padStart(2, "0")}:${s.toString().padStart(2, "0")}`}</p>
        <button onClick={() => setPaused(!paused)}>
          {paused ? "Start" : "Pause"}
        </button>
        <button onClick={() => reset()}>Reset</button>
        <button onClick={addDateToServer}>Save progress</button>
      </div>
    </>
  );
};
reactjs asynchronous setstate
1个回答
0
投票

我认为这是问题所在:

let [[h, m, s], setTime] = React.useState([hours, minutes, seconds]);

在哪里

h, m, s
将是未定义的。

改为使用对象:

let [{hours:h, minutes:m, seconds:s}, setTime] = React.useState({hours, minutes, seconds});

codesandbox 演示

© www.soinside.com 2019 - 2024. All rights reserved.