如何在React-hooks中创建计时器

用户名

我如何使用React-hooks创建动画计时器

这是我尝试过的完整代码

基本上我在尝试以动画环的形式显示剩余时间的进度。但是我以某种方式失败了

我刚刚跟随这个博客创建了动画计时器 https://css-tricks.com/how-to-create-an-animated-countdown-timer-with-html-css-and-javascript/

  function setRemainingPathColor(timeLeft) {
    const { alert, warning, info } = COLOR_CODES;
    console.log(dataFromDiv);
    if (timeLeft <= alert.threshold) {
      dataFromDiv.current
        .querySelectorAll("base-timer-path-remaining")
        .classList.remove(warning.color);
      dataFromDiv.current
        .querySelectorAll("base-timer-path-remaining")
        .classList.add(alert.color);
    } else if (timeLeft <= warning.threshold) {
      dataFromDiv.current
        .querySelectorAll("base-timer-path-remaining")
        .classList.remove(info.color);
      dataFromDiv.current
        .querySelectorAll("base-timer-path-remaining")
        .classList.add(warning.color);
    }
  }

  React.useEffect(() => {
    let timer;
    let timePassed = 0;
    let timeLeft;
    timer = counter > 0 && setTimeout(() => setCounter(counter - 1), 1000);
    timePassed = timePassed += 1;
    timeLeft = counter - timePassed;
    setRemainingPathColor(timeLeft);
    return () => {
      if (timer) {
        clearTimeout(timer);
      }
    };
  }, [counter]);
扎卡里·哈伯(Zachary Haber)

您得到的错误是因为dataFromDiv.current.querySelectorAll(...)总是返回undefined,因为要dataFromDiv.current对其进行引用div#base-timer-path-remaining是要修改的元素。因此,只需删除即可使您的代码正常工作.querySelectorAll(...)

但是,有一些更好的方法来组织代码:

代替直接进行dom操作,在这种情况下,更容易找出要使用哪种颜色useMemo基于计数器值设置派生数据。

您还可以使用间隔而不是计时器,因为它更易于使用并且更清洁。这也使用setCounter的updater函数形式,因此不需要counter在依赖项中具有效果

我还在下面的示例中添加了一个重置​​按钮,因此您不必每次都重新运行它。

  const pathColor = React.useMemo(() => {
    const { alert, warning, info } = COLOR_CODES;
    if (counter <= alert.threshold) {
      return alert.color;
    } else if (counter <= warning.threshold) {
      return warning.color;
    } else {
      return info.color;
    }
  }, [counter]);

  React.useEffect(() => {
    const timerId = setInterval(() => {
      setCounter(counter => {
        if (counter <= 0) {
          clearInterval(timerId);
          return counter;
        }
        return counter - 1;
      });
    }, 1000);
    return () => {
      clearInterval(timerId);
    };
  }, [timerReset]); // this timerReset is to make sure that the interval starts off again whenever the reset button is pressed.

这条线只是强制重新渲染的一种方法。每当调用调度(重命名为,reducer函数x=>x+1都会增加该timerResetresetTimer然后我使用timerReset强制效果重新运行以重新开始间隔(如果它已停止)

  const [timerReset, resetTimer] = React.useReducer(x => x + 1, 0);

const padTime = time => {
  return String(time).length === 1 ? `0${time}` : `${time}`;
};

const format = time => {
  const minutes = Math.floor(time / 60);
  const seconds = time % 60;
  return `${minutes}:${padTime(seconds)}`;
};

const WARNING_THRESHOLD = 10;
const ALERT_THRESHOLD = 5;

const COLOR_CODES = {
  info: {
    color: "green"
  },
  warning: {
    color: "orange",
    threshold: WARNING_THRESHOLD
  },
  alert: {
    color: "red",
    threshold: ALERT_THRESHOLD
  }
};

function App() {
  const [counter, setCounter] = React.useState(20);
  const [timerReset, resetTimer] = React.useReducer(x => x + 1, 0);
  const pathColor = React.useMemo(() => {
    const { alert, warning, info } = COLOR_CODES;
    if (counter <= alert.threshold) {
      return alert.color;
    } else if (counter <= warning.threshold) {
      return warning.color;
    } else {
      return info.color;
    }
  }, [counter]);

  React.useEffect(() => {
    const timerId = setInterval(() => {
      setCounter(counter => {
        if (counter <= 0) {
          clearInterval(timerId);
          return counter;
        }
        return counter - 1;
      });
    }, 1000);
    return () => {
      clearInterval(timerId);
    };
  }, [timerReset]);

  return (
    <div className="App">
      <div className="base-timer">
        <svg
          className="base-timer__svg"
          viewBox="0 0 100 100"
          xmlns="http://www.w3.org/2000/svg"
        >
          <g className="base-timer__circle">
            <circle
              className="base-timer__path-elapsed"
              cx="50"
              cy="50"
              r="45"
            />
            <path
              id="base-timer-path-remaining"
              className={`base-timer__path-remaining ${pathColor}`}
              d="
          M 50, 50
          m -45, 0
          a 45,45 0 1,0 90,0
          a 45,45 0 1,0 -90,0
        "
            />
          </g>
        </svg>
        <span id="base-timer-label" className="base-timer__label">
          {format(counter)}
        </span>
      </div>
      <button
        onClick={() => {
          setCounter(20);
          resetTimer();
        }}
      >
        reset timer
      </button>
    </div>
  );
}


const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);
/* Sets the containers height and width */
.base-timer {
  position: relative;
  height: 300px;
  width: 300px;
}

/* Removes SVG styling that would hide the time label */
.base-timer__circle {
  fill: none;
  stroke: none;
}

/* The SVG path that displays the timer's progress */
.base-timer__path-elapsed {
  stroke-width: 7px;
  stroke: grey;
}

.base-timer__path-remaining {
  stroke-width: 7px;
  stroke-linecap: round;
  transform: rotate(90deg);
  transform-origin: center;
  transition: 1s linear all;
  fill-rule: nonzero;
  stroke: currentColor;
}

.base-timer__path-remaining.green {
  color: rgb(65, 184, 131);
}

.base-timer__path-remaining.orange {
  color: orange;
}

.base-timer__path-remaining.red {
  color: red;
}

.base-timer__label {
  position: absolute;
  width: 300px;
  height: 300px;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 48px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
	<div id="root"></div>

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类常见问题

如何在JavaScript中创建准确的计时器?

来自分类Dev

如何在计时器中获取我的对象的实例

来自分类Dev

如何在Java Applet中创建倒数计时器?

来自分类Dev

如何在iOS中创建一个递增计时器

来自分类Dev

如何创建可重置计时器?

来自分类Dev

如何在单独的类中的iOS Swift中创建计时器?

来自分类Dev

如何创建“倒数计时器” GIF?

来自分类Dev

如何在JavaScript中创建计时器并计算指定时间的点击次数?

来自分类Dev

如何在JINT Javascript端创建计时器

来自分类Dev

React中的计时器有麻烦

来自分类Dev

按下按钮后如何在ModalView中创建倒数计时器?

来自分类Dev

如何在React中显示倒数计时器

来自分类Dev

如何在React-Hooks中重置计时器

来自分类Dev

如何在flutter中创建子计时器?

来自分类Dev

如何创建计时器功能?

来自分类Dev

如何在C#中创建计时器计数器

来自分类Dev

如何在vb.net中创建多个计时器处理程序

来自分类Dev

如何在Java Applet中创建倒数计时器?

来自分类Dev

如何在iOS中创建一个递增计时器

来自分类Dev

如何在不应重新加载页面的Java脚本中创建countdoun计时器

来自分类Dev

如何在批处理文件中创建计时器和循环?

来自分类Dev

如何创建可重置计时器?

来自分类Dev

如何在单独的类中的iOS Swift中创建计时器?

来自分类Dev

如何使用JLabel创建计时器?

来自分类Dev

如何在android programmaticaly中创建计时器?

来自分类Dev

如何创建倒数计时器

来自分类Dev

如何在python中为乒乓球创建计时器分数

来自分类Dev

如何为 WPF 创建计时器

来自分类Dev

如何在winform C#中为动态创建的标签添加计时器?

Related 相关文章

热门标签

归档