【问题标题】:Can't initialize state from props无法从道具初始化状​​态
【发布时间】:2020-08-30 08:33:09
【问题描述】:

首先,我知道关于这个主题有很多问题,而且我已经阅读了所有我认为适用于我的情况的问题。这个线程React component 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 存储区,如果这有什么不同的话。 当我在控制台中打印出“分钟”时,我得到了未定义,当它被渲染时,我只得到了 NaN 分钟。如何使 props.workPeriod 进入状态,以便对其进行定义并能够对其进行操作?

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

提前致谢!

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

【问题讨论】:

  • 在构造函数块中使用console.log(props.workPeriod)会得到什么?
  • 好问题!我不确定。但是我怎么还能在 DOM 中毫无问题地渲染 this.props.workPeriod
  • 我为你的问题添加了答案

标签: reactjs redux redux-form react-props react-state


【解决方案1】:

这是因为 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;

【讨论】:

  • 做到了!一开始我使用的是 React Hooks,但后来我遇到了条件渲染的问题,所以我改用基于类的组件。但我已经简化了渲染问题,所以效果很好。
【解决方案2】:

const {minutes, seconds} = this.setState

你是说

const {minutes, seconds} = this.state?

【讨论】:

  • 我实际上在早期的迭代中将它作为this.state,我将其更改为this.setState 只是为了看看会发生什么,并没有什么不同,所以我只是保留了它。我刚才把它改回this.state 只是为了确定,但我注意到它仍然没有任何区别。
  • 好的,除非有一些我不知道的隐藏行为,否则const {...} = this.setState 将不起作用,因为setState 是一个函数。 this.state 是实际包含状态变量的对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-23
  • 2019-05-08
  • 2019-07-12
  • 2018-03-20
  • 2020-10-30
  • 1970-01-01
  • 2022-08-22
相关资源
最近更新 更多