代码之家  ›  专栏  ›  技术社区  ›  Mehmood Ahmad

在react redux中分派2个同步操作时,状态不会在第一个操作时更新

  •  2
  • Mehmood Ahmad  · 技术社区  · 8 年前

    pomodoro clock 作为FreeCodeCamp的实践项目。这是一个简单的时钟,只要当前计时器结束,它就会在会话时间和中断时间之间切换。

    我现在面临的问题是在react中的redux。这是我的应用程序启动时的状态。

    Initial State

    当我单击减号或加号时,商店中的计时器和会话/中断长度将相应地更新,但这并没有发生。会话/中断长度将更新,但计时器将反映上一个值。这是我增加会话时反映问题的屏幕截图

    Increase Session

    updateSettings(type) {
    
        if (!this.props.isPlaying) {
    
            let isInvalid = false; // to show alert if user input is invalid
    
            if (type === 'increase-session') {
                this.props.increaseSession();
            } else if (type === 'decrease-session') {
                (this.props.session_length > 1) ? this.props.decreaseSession() : isInvalid = true;
            } else if (type === 'increase-break') {
                this.props.increaseBreak();
            } else if (type === 'decrease-break') {
                (this.props.break_length > 1) ? this.props.decreaseBreak() : isInvalid = true;
            }
    
            if (isInvalid) {
                alert("Times less than 1 minutes is not allowed.");
            } else {
                this.props.setTimer({
                    minutes: this.props.session_length,
                    seconds: 0,
                    percentage: this.getTimeElapsedPercentage(this.props.session_length, 0)
                });
            }
        }
    }
    

    在上面的代码中,所有操作都是同步的,当我调用 this.props.increaseSession() 然后它发送增加会话的操作。然后我打电话 this.props.timer(timerObj)

    我的问题是所有的动作都是同步的,那么为什么我在发送 setTimer() . 任何解决这个问题的建议都将非常感谢。

    this.props.session_length 但这不是正确的会话长度。会话长度也在内部使用 getTimeElapsedPercentage 这就是问题的根源。我可以用一些逻辑来解决这个问题,但我希望得到正确的解决方案,而不是绕道而行。

    getTimeElapsedPercentage(minutes, seconds) {
        let totalTimeInSec, timeElapsedInSec, timeRemainingInSec;
    
        this.props.playType === 'break' ?
            totalTimeInSec = this.props.break_length * 60 :
            totalTimeInSec = this.props.session_length * 60;
    
        timeRemainingInSec = minutes * 60 + seconds;
        timeElapsedInSec = totalTimeInSec - timeRemainingInSec;
    
        return timeElapsedInSec / totalTimeInSec * 100;
    }
    

    解决方案(解决方法-正确答案如下)

    this.props.session_长度 当我使用 setTimer(timerObj) .

    所以我想到了这个办法。在第一个操作之后,我的存储被更新,但是道具没有更新,所以我从我的redux代码导入存储并使用 store.getState() 设置计时器(timerObj) 这就解决了问题。

    2 回复  |  直到 8 年前
        1
  •  1
  •   Roy Scheffers suresh sunkari    8 年前

    我想 updateSettings(type) 每次单击用于增加会话或中断的按钮时调用。在这种情况下,当调用函数并到达 this.props.increaseSession() this.props.decreaseSession() 部分,JavaScript引擎调用这些函数,它将执行它的任务。同时编译器继续下一行并到达

    if (isInvalid) {
      alert("Times less than 1 minutes is not allowed.");
    } else {
      this.props.setTimer({
        minutes: this.props.session_length,
        seconds: 0,
        percentage: this.getTimeElapsedPercentage(this.props.session_length, 0)
      });
    }
    

    此时增加或减少会话调用尚未完成,因此 this.props.session_length

    我的建议是移动设置 session_length

    minutes: this.props.session_length + 1 minutes: this.props.session_length - 1 当你打电话给下面的人。

    this.props.setTimer({
      minutes: this.props.session_length,
      seconds: 0,
      percentage: this.getTimeElapsedPercentage(this.props.session_length, 0)
    });
    

    要解决百分比问题,可以更新 getTimeElapsedPercentage 接受一个额外的论点 plusMinus

    getTimeElapsedPercentage(minutes, seconds, plusMinus) {
        let totalTimeInSec, timeElapsedInSec, timeRemainingInSec;
    
        this.props.playType === 'break' ?
            totalTimeInSec = (this.props.break_length + plusMinus) * 60 :
            totalTimeInSec = (this.props.session_length + plusMinus) * 60;
    
        timeRemainingInSec = minutes * 60 + seconds;
        timeElapsedInSec = totalTimeInSec - timeRemainingInSec;
    
        return timeElapsedInSec / totalTimeInSec * 100;
    }
    

    在updateSettings中设置if语句

    let plusMinus = 0; 
    if (type === 'increase-session') {
      plusMinus = 1;
    } else if (type === 'decrease-session') {
      plusMinus = -1;
    }
    

    电话如下

    percentage: this.getTimeElapsedPercentage(this.props.session_length, 0, plusMinus)
    

    我希望这有助于项目的顺利进行。

        2
  •  1
  •   Mehmood Ahmad    8 年前

    this.props.setTimer 在渲染之前使用道具 this.props.session_length 价值。这可以通过使用 componentDidUpdate()

    • 删除 setTimer() 从你的 updateSettings(type) 功能。因此道具只更新一次(即在increasession、decresession等上)
    • 在组件中添加以下代码

    componentDidUpdate(prevProps) {
            if (this.props.session_length !== prevProps.session_length) {
                this.props.setTimer({
                    minutes: this.props.session_length,
                    seconds: 0,
                    percentage: this.getTimeElapsedPercentage(this.props.session_length, 0)
                });
            }
        }