【问题标题】:How to seperate the two functions in ReactJS?如何在 ReactJS 中分离两个函数?
【发布时间】:2022-01-04 14:58:29
【问题描述】:

简介

我正在构建倒数计时器,我已经构建了它,但现在我想扩大它。所以我在同一页面上构建了两个倒计时,每个倒计时都有单独的startstop 按钮和常见的reset 按钮。

我有什么?

我已经实施了,但他们没有独立工作。 例如,当我点击上时钟的停止时,它也会停止下时钟。

我想要什么?

我想在同一个页面上为这两个函数设置单独的函数。

代码

代码中的大部分内容都是重复的。

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

const STATUS = {
  STARTED: "Started",
  STOPPED: "Stopped"
};

const STATUSp1 = {
  STARTED: "Started",
  STOPPED: "Stopped"
};

export default function InputCountDown() {
  const [time, setTime] = useState(0);
  const [timep1, setTimep1] = useState(0);
  const [inc, setInc] = useState(0);

  const handleOnChange = (e) => {
    //console.log(e.target.value);
    setTime(e.target.value);
    setTimep1(e.target.value);
  };

  const handleOnChangeIncrement = (e) => {
    console.log(e.target.value);
    setInc(e.target.value);
  };

  const [secondsRemaining, setSecondsRemaining] = useState(time * 60);
  const [secondsRemainingp1, setSecondsRemainingp1] = useState(timep1 * 60);

  //console.log(time);

  const [status, setStatus] = useState(STATUS.STOPPED);
  const [statusp1, setStatusp1] = useState(STATUSp1.STOPPED);

  const secondsToDisplay = secondsRemaining % 60;
  const minutesRemaining = (secondsRemaining - secondsToDisplay) / 60;
  const minutesToDisplay = minutesRemaining % 60;
  const hoursToDisplay = (minutesRemaining - minutesToDisplay) / 60;

  const secondsToDisplayp1 = secondsRemainingp1 % 60;
  const minutesRemainingp1 = (secondsRemainingp1 - secondsToDisplayp1) / 60;
  const minutesToDisplayp1 = minutesRemainingp1 % 60;
  const hoursToDisplayp1 = (minutesRemainingp1 - minutesToDisplayp1) / 60;

  const handleStart = () => {
    setStatus(STATUS.STARTED);
    setSecondsRemaining(time * 60);
  };

  const handleStartp1 = () => {
    setStatusp1(STATUSp1.STARTED);
    setSecondsRemainingp1(timep1 * 60);
  };

  const handleStop = () => {
    setStatus(STATUS.STOPPED);
  };

  const handleStopp1 = () => {
    setStatusp1(STATUSp1.STOPPED);
  };

  const handleReset = () => {
    setStatus(STATUS.STOPPED);
    setSecondsRemaining(time * 60);
    setSecondsRemainingp1(timep1 * 60);
  };

  useInterval(
    () => {
      if (secondsRemaining > 0) {
        setSecondsRemaining(secondsRemaining - 1);
      } else {
        setStatus(STATUS.STOPPED);
      }

      if (secondsRemainingp1 > 0) {
        setSecondsRemainingp1(secondsRemainingp1 - 1);
      } else {
        setStatusp1(STATUSp1.STOPPED);
      }
    },
    status === STATUS.STARTED ? 1000 : null,
    statusp1 === STATUSp1.STARTED ? 1000 : null
    // passing null stops the interval
  );
  return (
    <>
      <div className="App">
        <h1>Countdown Using Input</h1>
        <div style={{ padding: "12px" }}>
          <label htmlFor="time"> Enter time in minutes </label>
          <input
            type="text"
            id="time"
            name="time"
            value={time}
            onChange={(e) => handleOnChange(e)}
          />
        </div>
        <div style={{ padding: "12px" }}>
          <label htmlFor="inc"> Enter increment </label>
          <input
            type="number"
            id="inc"
            name="inc"
            value={inc}
            onChange={(e) => handleOnChangeIncrement(e)}
          />
        </div>

        <button onClick={handleStart} type="button">
          Start
        </button>
        <button onClick={handleStop} type="button">
          Stop
        </button>
        <button onClick={handleReset} type="button">
          Reset
        </button>
        <div>
          <button
            onClick={() =>
              setSecondsRemaining(secondsRemaining + parseInt(inc, 10))
            }
          >
            Increment {inc} sec
          </button>
        </div>
        <div style={{ padding: 20, fontSize: "40px" }}>
          {twoDigits(hoursToDisplay)}:{twoDigits(minutesToDisplay)}:
          {twoDigits(secondsToDisplay)}
        </div>
        <div>Status: {status}</div>
        <div style={{ padding: 20, fontSize: "40px" }}>
          {twoDigits(hoursToDisplayp1)}:{twoDigits(minutesToDisplayp1)}:
          {twoDigits(secondsToDisplayp1)}
        </div>
        <button onClick={handleStartp1} type="button">
          Start_p1
        </button>
        <button onClick={handleStopp1} type="button">
          Stop_p1
        </button>
        <button onClick={handleReset} type="button">
          Reset_p1
        </button>
      </div>
    </>
  );
}

// source: https://overreacted.io/making-setinterval-declarative-with-react-hooks/
function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

// https://stackoverflow.com/a/2998874/1673761
const twoDigits = (num) => String(num).padStart(2, "0");

您也可以在 inputCountDown.js 文件的代码框内找到代码。

您可以忽略增量按钮

请帮帮我!!!

【问题讨论】:

  • 首先,您将三个参数传递给useInterval,但该函数只需要两个。这是一个非常愚蠢的错误,应该被 linter 发现。

标签: javascript reactjs react-native react-hooks react-router


【解决方案1】:

您对两个不同的计数器使用相同的时间间隔,这导致它们同时同步。然而,这段代码一次处理的职责太多,并且包含不必要的重复,污染了代码的可读性。

不要使用不同的变量名称复制相同的代码,而是尝试将其提取到自己的组件中,然后调用该组件两次。这样,可以确保更多的代码隔离,并且绝对不易出错,同时提高可读性。

【讨论】:

  • 是的,但后来两个时钟之间存在互连,这就是为什么将它们保持在同一个组件中的原因。
  • 即使这样,您也可以提取组件的互连部分并在父组件中使用它,这比保留相同代码的两个副本阻塞父组件的功能要好得多。
【解决方案2】:

为每个定时器分离 useInterval 逻辑

  useInterval(
    () => {
      if (secondsRemaining > 0) {
        setSecondsRemaining(secondsRemaining - 1);
      } else {
        setStatus(STATUS.STOPPED);
      }
    },
    status === STATUS.STARTED ? 1000 : null
  );

  useInterval(
    () => {
      if (secondsRemainingp1 > 0) {
        setSecondsRemainingp1(secondsRemainingp1 - 1);
      } else {
        setStatusp1(STATUSp1.STOPPED);
      }
    },
    statusp1 === STATUSp1.STARTED ? 1000 : null
    // passing null stops the interval
  );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    相关资源
    最近更新 更多