无法从道具初始化状​​态

Can't initialize state from props

首先,我知道有很多关于这个主题的问题,我已经通读了所有我认为适用于我的情况的问题。这个线程 似乎是我特别需要的,但这里提到的都没有用。无论如何,进入我的代码。它只是一个简单的倒计时计时器,它的起点是用户输入(以分钟为单位):

class Timer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            minutes: props.workPeriod,
            seconds: 0
        };
      }
    componentDidMount() {  
        setInterval(() => {
            const {minutes, seconds} = this.state
            console.log("minute state: ", minutes)
            if(this.props.countdownHasStarted) {
                if(seconds > 0) {
                    this.setState(({seconds}) => ({
                        seconds: seconds - 1
                    }))
                }
                if(seconds === 0) {
                    if(minutes === 0) {
                        clearInterval(this.myInterval)
                    } else {
                        this.setState(({minutes}) => ({
                            minutes: minutes - 1,
                            seconds: 59
                        }))
                    }
                }
            }
        }, 1000)
    }

...

const selector = formValueSelector('intervalSettings')
Timer = connect(state => {
    const workPeriod = selector(state, 'workPeriod')
    return {
        workPeriod,
        countdownHasStarted: state.countdownHasStarted
    }
})(Timer)

由于一切都位于组件树上的位置,我使用了 Redux,所以 workPeriod 来自 Redux 商店,如果这有什么不同的话。 当我在控制台中打印出 'minutes' 时,我得到了 undefined,并且当它被渲染时果然,我只是在几分钟内得到 NaN。我如何让 props.workPeriod 进入状态以便它被定义并能够被操纵?

我包括了我是如何从 Redux 商店获得 workPeriod 的,以防万一我的问题与此有关,但是 {this.props.workPeriod} 呈现得很好,所以我认为那里一切都很好。

提前致谢!

(经过编辑以纳入之前的建议和问题)

const {minutes, seconds} = this.setState

你的意思是

const {minutes, seconds} = this.state?

发生这种情况是因为 redux 存储是用一个空对象初始化的。当 redux-form reducer 初始化它自己的 initialValues 时,<Timer /> 组件得到一个未定义的值 workPeriod 并启动 setInterval()。以下是我将如何使用 React Hooks 解决这个问题:

import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { formValueSelector } from "redux-form";

let Timer = ({ workPeriod, countdownHasStarted }) => {
  const [seconds, setSeconds] = useState(0);
  const [minutes, setMinutes] = useState();

  useEffect(() => {
    // first initialize the minutes when the workPeriod is initialized
    setMinutes(workPeriod);
  }, [workPeriod]);

  useEffect(() => {
    let interval;
    if (minutes) {
      interval = setInterval(() => {
        console.log("minute state: ", minutes);
        if (countdownHasStarted) {
          if (seconds > 0) {
            setSeconds((sec) => sec - 1);
          }
          if (seconds === 0) {
            if (minutes === 0) {
              clearInterval(interval);
            } else {
              setMinutes((min) => min - 1);
              setSeconds(59);
            }
          }
        }
      }, 1000);
    }

    return () => {
      // cleanup function
      clearInterval(interval);
    };
  }, [countdownHasStarted, minutes, seconds]);

  return (
    <div className="numbers">
      <div className="box" id="minutes">
        <p>{minutes}</p>
      </div>
      <div className="box" id="colon">
        <p>:</p>
      </div>
      <div className="box" id="seconds">
        <p>{seconds < 10 ? `0${seconds}` : seconds}</p>
      </div>
    </div>
  );
};

Timer = connect((state) => {
  const selector = formValueSelector("intervalSettings");
  const workPeriod = selector(state, "workPeriod");
  return {
    workPeriod,
    countdownHasStarted: state.countdownHasStarted,
  };
})(Timer);

export default Timer;