亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

set狀態不會立即在設置內部更新狀態

set狀態不會立即在設置內部更新狀態

FFIVE 2022-09-29 15:47:59
我正在嘗試構建一個模擬時鐘,秒針每秒旋轉一次,最小指針每分鐘旋轉6度,小時指針每12分鐘旋轉6度。這是代碼和框:https://codesandbox.io/s/react-example-d7mes?file=/Clock.js每當最小指針的角度為其中任何一個(12分鐘度)時,我都會將時針旋轉6度一次。[72, 144, 216, 288, 360]這就是我正在做的事情: let twelveMinDegrees = [72, 144, 216, 288, 360]; setInterval(() => {        this.setState(prev => ({            sec: prev.sec == 360 ? 6 : prev.sec + 6,  //degrees            min: prev.sec == 354 ? (prev.min == 360 ? 6 : prev.min + 6) : prev.min,  //degrees            hrs: (function(){  //degrees                const indx = twelveMinDegrees.findIndex(el => el == prev.min)                if(!minChanged && indx >=0){ //only change once for every 12min                    minChanged = true;                     let incHrs = prev.hrs + (6*indx);                    console.log(incHrs);                    return incHrs;                 }else{                    if(!twelveMinDegrees.includes(prev.min)){                        minChanged = false;                    }                    return prev.hrs;                }            })()         }))    }, 1000)但是時針不會改變,并且第二次被設置回other部分中的上一個值,并且返回的值被忽略,因為在狀態更新之前,稱為下一秒,它返回的仍然是舊值(不是在incHrselseprev.hrsif(!minChanged && indx >=0))如何解決此問題?
查看完整描述

1 回答

?
滄海一幻覺

TA貢獻1824條經驗 獲得超5個贊

這里有一個基本的設計問題,那就是設置間隔是保持時間的錯誤工具。 只保證回調不會運行至少1000毫秒,而不是保證它將在1000毫秒內完全運行,所以你最終會得到漂移和跳過的時間。setInterval

我建議使用請求動畫幀日期庫或性能來確定何時發生了刻度。

通過此設置,您可以使用以下命令將時針與小時剩余的分鐘數成比例地縮放:

(hours + minutes / 60) * 30 + 180

如果您希望對時針調整進行更粗糙的粒度,請將分鐘截斷為 6 個不同的塊:

(hours + floor(minutes / 10) * 10 / 60) * 30 + 180

在數學上執行此操作比在硬編碼數組中查找增量點要混亂得多。

下面是一個最小的示例,可用于保持準確的時間(我將樣式留給您):

.hand {

  width: 2px;

  height: 40%;

  background-color: black;

  transform-origin: top center;

  position: absolute;

  border-radius: 3px;

  top: 50%;

  left: 50%;

}


.analog-clock {

  position: relative;

  border-radius: 50%;

  border: 1px solid #aaa;

  height: 120px;

  width: 120px;

}

<script type="text/babel" defer>

const {Fragment, useEffect, useState, useRef} = React;


const Clock = () => {

  const [date, setDate] = useState(new Date());

  const requestRef = useRef();

  let prevDate = null;

  

  const tick = () => {

    const now = new Date();

    

    if (prevDate && now.getSeconds() !== prevDate.getSeconds()) {

      setDate(now);

    }

    

    prevDate = now;

    requestRef.current = requestAnimationFrame(tick);

  };

  

  useEffect(() => {

    requestRef.current = requestAnimationFrame(tick);

    return () => cancelAnimationFrame(requestRef.current);

  }, []);

  

  const pad = n => n.toString().padStart(2, 0);

  

  const computeHourDeg = date => 

    (date.getHours() + ~~(date.getMinutes() / 10) * 10 / 60) * 30 + 180

  ;


  return (

    <Fragment>

      <div className="analog-clock">

        <div

          className="hand"

          style={{transform: `rotate(${6 * date.getSeconds() + 180}deg)`}}

        ></div>

        <div

          className="hand"

          style={{transform: `rotate(${6 * date.getMinutes() + 180}deg)`}}

        ></div>

        <div

          className="hand"

          style={{background: "red", 

                  height: "30%",

                  transform: `rotate(${computeHourDeg(date)}deg)`}}

        ></div>

      </div>

      <h3>

        {pad(date.getHours())}:

        {pad(date.getMinutes())}:

        {pad(date.getSeconds())}

      </h3>

    </Fragment>

  );

};


ReactDOM.render(<Clock />, document.body);


</script>


<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>

下面是一個帶有模擬對象的加速版本,用于說明它工作正常:Date

.hand {

  width: 2px;

  height: 40%;

  background-color: black;

  transform-origin: top center;

  position: absolute;

  border-radius: 3px;

  top: 50%;

  left: 50%;

}


.analog-clock {

  position: relative;

  border-radius: 50%;

  border: 1px solid #aaa;

  height: 120px;

  width: 120px;

}

<script type="text/babel" defer>

const {Fragment, useEffect, useState, useRef} = React;


const speedMS = 5;


class MockDate {

  static second = 0;

  static minute = 0;

  static hour = 0;

  

  constructor() {

    this.second = MockDate.second;

    this.minute = MockDate.minute;

    this.hour = MockDate.hour;

  }

  

  getSeconds() {

    return this.second;

  }

  

  getMinutes() {

    return this.minute;

  }

  

  getHours() {

    return this.hour || 12;

  }

}


setInterval(() => {

  if (++MockDate.second === 60) {

    MockDate.second = 0;


    if (++MockDate.minute === 60) {

      MockDate.minute = 0;

      MockDate.hour = (MockDate.hour + 1) % 12;

    }

  }

}, speedMS);


const Clock = () => {

  const [date, setDate] = useState(new MockDate());

  const requestRef = useRef();

  let prevDate = null;


  const tick = () => {

    const now = new MockDate();


    if (prevDate && now.getSeconds() !== prevDate.getSeconds()) {

      setDate(now);

    }


    prevDate = now;

    requestRef.current = requestAnimationFrame(tick);

  };


  useEffect(() => {

    requestRef.current = requestAnimationFrame(tick);

    return () => cancelAnimationFrame(requestRef.current);

  }, []);


  const pad = n => n.toString().padStart(2, 0);


  const computeHourDeg = date => 

    (date.getHours() + ~~(date.getMinutes() / 10) * 10 / 60) * 30 + 180

  ;


  return (

    <Fragment>

      <div className="analog-clock">

        <div

          className="hand"

          style={{transform: `rotate(${6 * date.getSeconds() + 180}deg)`}}

        ></div>

        <div

          className="hand"

          style={{transform: `rotate(${6 * date.getMinutes() + 180}deg)`}}

        ></div>

        <div

          className="hand"

          style={{background: "red", 

                  height: "30%",

                  transform: `rotate(${computeHourDeg(date)}deg)`}}

        ></div>

      </div>

      <h3>

        {pad(date.getHours())}:

        {pad(date.getMinutes())}:

        {pad(date.getSeconds())}

      </h3>

    </Fragment>

  );

};



ReactDOM.render(<Clock />, document.body);


</script>


<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>


查看完整回答
反對 回復 2022-09-29
  • 1 回答
  • 0 關注
  • 155 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號