将React应用从类转换为钩子

时间:2020-09-10 10:09:19

标签: reactjs react-hooks

我有这个用类编写的Pomodoro react应用程序,我想转换为钩子。

setInterval

我进行了以下更改,尽管一切似乎都可以正常工作,但并非关键的一件事是handlePlayPause函数中的import React, { useState, useEffect } from 'react'; import SetTimer from './components/SetTimer'; import './App.css'; const App = () => { let loop = undefined; const [timeVariables, setTimeVariables] = useState({ breakCount: 5, sessionCount: 25, clockCount: 25 * 60, currentTimer: 'Session', isPlaying: false, }); const { breakCount, sessionCount, clockCount, currentTimer, isPlaying, } = timeVariables; useEffect(() => { return () => { clearInterval(loop); }; }, []); const handlePlayPause = () => { const { isPlaying } = timeVariables; if (isPlaying) { clearInterval(loop); setTimeVariables({ ...timeVariables, isPlaying: false }); } else { setTimeVariables({ ...timeVariables, isPlaying: true }); loop = setInterval(() => { console.log('Hello'); const { clockCount, breakCount, sessionCount, currentTimer, } = timeVariables; if (clockCount === 0) { setTimeVariables({ ...timeVariables, currentTimer: currentTimer === 'Session' ? 'Break' : 'Session', clockCount: currentTimer === 'Session' ? breakCount * 60 : sessionCount * 60, }); } else { setTimeVariables({ ...timeVariables, clockCount: clockCount - 1 }); } }, 1000); } }; const handleReset = () => { setTimeVariables({ breakCount: 5, sessionCount: 25, clockCount: 25 * 60, currentTimer: 'Session', isPlaying: false, }); clearInterval(loop); }; const convertTime = (count) => { const minutes = Math.floor(count / 60); let seconds = count % 60; seconds = seconds < 10 ? `0${seconds}` : `${seconds}`; return `${minutes}:${seconds}`; }; const handleBreakDecrease = () => { const { breakCount } = timeVariables; if (breakCount >= 2) { setTimeVariables({ ...timeVariables, breakCount: breakCount - 1 }); } }; const handleBreakIncrease = () => { const { breakCount } = timeVariables; setTimeVariables({ ...timeVariables, breakCount: breakCount + 1 }); }; const handleSessionDecrease = () => { const { sessionCount } = timeVariables; if (sessionCount >= 2) { setTimeVariables({ ...timeVariables, sessionCount: sessionCount - 1, clockCount: (sessionCount - 1) * 60, }); } }; const handleSessionIncrease = () => { const { sessionCount } = timeVariables; setTimeVariables({ ...timeVariables, sessionCount: sessionCount + 1, clockCount: (sessionCount + 1) * 60, }); }; const breakProps = { title: 'Break Length', count: breakCount, handleDecrease: handleBreakDecrease, handleIncrease: handleBreakIncrease, }; const sessionProps = { title: 'Session Length', count: sessionCount, handleDecrease: handleSessionDecrease, handleIncrease: handleSessionIncrease, }; return ( <div> <div className='flex'> <SetTimer {...breakProps} /> <SetTimer {...sessionProps} /> </div> <div className='clock-container'> <h1>{currentTimer}</h1> <span>{convertTime(clockCount)}</span> <div className='flex'> <button onClick={handlePlayPause}> {isPlaying ? ( <i className={`fas fa-pause`}></i> ) : ( <i className='fas fa-play'></i> )} </button> <button onClick={handleReset}> <i className='fas fa-sync-alt'></i> </button> </div> </div> </div> ); }; export default App; 函数仅运行一次。我不知道为什么!

import React, { useState, useEffect } from 'react';
import SetTimer from './components/SetTimer';
import './App.css';

const App = () => {
  console.log('rendered');
  let loop = undefined;
  // const [loop, setLoop] = useState(undefined);
  const [breakCount, setBreakCount] = useState(5);
  const [sessionCount, setSessionCount] = useState(25);
  const [clockCount, setClockCount] = useState(25 * 60);
  const [currentTimer, setCurrentTimer] = useState('Session');
  const [isPlaying, setIsPlaying] = useState(false);

  // const [timeVariables, setTimeVariables] = useState({
  //   breakCount: 5,
  //   sessionCount: 25,
  //   clockCount: 25 * 60,
  //   currentTimer: 'Session',
  //   isPlaying: false,
  // });

  // const {
  //   breakCount,
  //   sessionCount,
  //   clockCount,
  //   currentTimer,
  //   isPlaying,
  // } = timeVariables;

  // useEffect(() => {
  //   // setClockCount(
  //   //   currentTimer === 'Session' ? sessionCount * 60 : breakCount * 60
  //   // );
  //   return () => {
  //     clearInterval(loop);
  //   };
  // }, []);

  const handlePlayPause = () => {
    // const { isPlaying } = timeVariables;
    if (isPlaying) {
      console.log(loop, isPlaying);
      clearInterval(loop);
      setIsPlaying(false);
    } else {
      loop = setInterval(() => {
        console.log(loop, isPlaying);
        setIsPlaying(true);
        // const {
        //   clockCount,
        //   breakCount,
        //   sessionCount,
        //   currentTimer,
        // } = timeVariables;
        if (clockCount === 0) {
          setCurrentTimer(currentTimer === 'Session' ? 'Break' : 'Session');
          setClockCount(
            currentTimer === 'Session' ? breakCount * 60 : sessionCount * 60
          );
          // setTimeVariables({
          //   ...timeVariables,
          //   currentTimer: currentTimer === 'Session' ? 'Break' : 'Session',
          //   clockCount:
          //     currentTimer === 'Session' ? breakCount * 60 : sessionCount * 60,
          // });
        } else {
          setClockCount((clockCount) => clockCount - 1);
          // setTimeVariables({ ...timeVariables, clockCount: clockCount - 1 });
        }
      }, 1000);
    }
  };
  const handleReset = () => {
    setBreakCount(5);
    setSessionCount(25);
    setClockCount(25 * 60);
    setCurrentTimer('Session');
    setIsPlaying(false);
    // setTimeVariables({
    //   breakCount: 5,
    //   sessionCount: 25,
    //   clockCount: 25 * 60,
    //   currentTimer: 'Session',
    //   isPlaying: false,
    // });
    clearInterval(loop);
  };

  const convertTime = (count) => {
    const minutes = Math.floor(count / 60);
    let seconds = count % 60;
    seconds = seconds < 10 ? `0${seconds}` : `${seconds}`;
    return `${minutes}:${seconds}`;
  };

  const handleBreakDecrease = () => {
    // const { breakCount } = timeVariables;
    if (breakCount >= 2) {
      setBreakCount(breakCount - 1);
      // setTimeVariables({ ...timeVariables, breakCount: breakCount - 1 });
    }
  };
  const handleBreakIncrease = () => {
    // const { breakCount } = timeVariables;
    setBreakCount(breakCount + 1);
    // setTimeVariables({ ...timeVariables, breakCount: breakCount + 1 });
  };
  const handleSessionDecrease = () => {
    // const { sessionCount } = timeVariables;
    if (sessionCount >= 2) {
      setSessionCount(sessionCount - 1);
      setClockCount((sessionCount - 1) * 60);
      // setTimeVariables({
      //   ...timeVariables,
      //   sessionCount: sessionCount - 1,
      //   clockCount: (sessionCount - 1) * 60,
      // });
    }
  };
  const handleSessionIncrease = () => {
    setSessionCount(sessionCount + 1);
    setClockCount((sessionCount + 1) * 60);
    // const { sessionCount } = timeVariables;
    // setTimeVariables({
    //   ...timeVariables,
    //   sessionCount: sessionCount + 1,
    //   clockCount: (sessionCount + 1) * 60,
    // });
  };

  const breakProps = {
    title: 'Break Length',
    count: breakCount,
    handleDecrease: handleBreakDecrease,
    handleIncrease: handleBreakIncrease,
  };

  const sessionProps = {
    title: 'Session Length',
    count: sessionCount,
    handleDecrease: handleSessionDecrease,
    handleIncrease: handleSessionIncrease,
  };

  return (
    <div>
      <div className='flex'>
        <SetTimer {...breakProps} />
        <SetTimer {...sessionProps} />
      </div>
      <div className='clock-container'>
        <h1>{currentTimer}</h1>
        <span>{convertTime(clockCount)}</span>
        <div className='flex'>
          <button onClick={handlePlayPause}>
            {isPlaying ? (
              <i className={`fas fa-pause`}></i>
            ) : (
              <i className='fas fa-play'></i>
            )}
          </button>
          <button onClick={handleReset}>
            <i className='fas fa-sync-alt'></i>
          </button>
        </div>
      </div>
    </div>
  );
};

export default App;

更新:带有各个状态变量

{{1}}

1 个答案:

答案 0 :(得分:1)

两个版本之间非常明显的区别是 在前者中,循环处于状态。 但是在后者中,循环只是一个变量。

您可能还希望使用State进行循环。但是,我强烈反对将useState与对象(和数组)一起使用。比较浅,所以有时可能不正确。

我知道当您必须为每个字段使用State时感到沮丧。看一下useReducer。检查这篇文章。这可能会有所帮助。 https://dev.to/max_frolov_/react-hooks-usereducer-complex-state-handling-243k