反应useState和useEffect嵌套。这个可以吗?

时间:2020-07-20 07:16:54

标签: reactjs react-hooks

我正在玩React钩子,并且正在尝试制作一个非常基本的时钟。它工作正常,花花公子,即使分析器说也没有奇怪的退缩。让我有些担心的部分是useEffect调用updateTimeAndDate的地方,该状态会更改状态。我觉得应该进入重新渲染循环。为什么仍然可以使用?对不起,我不能再说了。 :D

还会好一点吗?在这里:

const addZero = (trunk) => (trunk >= 10 ? "" : "0") + trunk;

const [hours, setHours] = useState(addZero(0));
const [minutes, setMinutes] = useState(addZero(0));

let timeAndDate;

function updateTimeAndDate() {
  timeAndDate = new Date();

  setHours(addZero(timeAndDate.getHours()));
  setMinutes(addZero(timeAndDate.getMinutes()));
}

useEffect(() => {
  updateTimeAndDate();
});

setInterval(updateTimeAndDate, 500);

我将useEffect放在那里,以便在加载页面后立即更新时间,而不是等待很长半秒。

2 个答案:

答案 0 :(得分:1)

您显示的代码会遇到几个问题:

  • 您将运行一个无限循环,使您的组件快速重新呈现。这是因为您要在每个渲染上调用setInterval,并且通过在updateTimeAndDate中调用setInterval来更新状态,这又会导致组件重新渲染。

  • 您尚未在useEffect中指定依赖项数组,因此它将在每次重新渲染时运行,从而进一步扩大了无限循环问题。

一种可能的选择是通过指定一个空的依赖项数组仅调用useEffect。您还可以清除卸载组件的时间间隔(通过在useEffect中指定一个返回值)。

这是一个代码框,显示:https://codesandbox.io/s/stack-overflow-set-interval-89spq

import React, { useState, useEffect } from "react";
import "./styles.css";

export default function App() {
  const addZero = trunk => (trunk >= 10 ? "" : "0") + trunk;

  const [hours, setHours] = useState(addZero(0));
  const [minutes, setMinutes] = useState(addZero(0));
  const [seconds, setSeconds] = useState(addZero(0));

  let timeAndDate;

  function updateTimeAndDate() {
    timeAndDate = new Date();

    setHours(addZero(timeAndDate.getHours()));
    setMinutes(addZero(timeAndDate.getMinutes()));
    setSeconds(addZero(timeAndDate.getSeconds()));
  }

  useEffect(() => {
    const interval = setInterval(updateTimeAndDate, 1000);
    return () => clearInterval(interval);
  }, []);

  // setInterval(updateTimeAndDate, 500);

  return (
    <div className="App">
      <h1>{hours}</h1>
      <h2>{minutes}</h2>
      <h3>{seconds}</h3>
    </div>
  );
}

答案 1 :(得分:0)

回答您的问题

可以吗?

catalogue = [["Lenova Yoga Tablet", 4000], ["Macbook Air", 8000], ["Apple iPad", 500], ["Samsung Galaxy A7", 200]] for i in catalogue: print("{}. {}, {}".format(str(i+1), catalogue[i][0], str(catalogue[i][1]))) 内调用updateTimeAndDate(更新状态)是可以的。但是,在您当前的代码中,您将遇到@RobertCooper提到的间隔问题。

但是,我在一件事情上与罗伯特不同意。这就是您将陷入无限循环。这使我们想到了第二个问题:

我觉得应该进入重新渲染循环。为什么它仍然可以工作?

由于React处理效果的方式,您当前的代码不会陷入无限循环。

根据documentation

如果将状态挂钩更新为与当前状态相同的值,React将在不渲染子代或发射效果的情况下纾困。

因此,当您在同一小时同一分钟更新状态时,React不会触发效果。因此,在这种特殊情况下不会出现无限循环。