簡體   English   中英

為什么事件處理程序 function 無法獲取更新后的 state object 值?

[英]Why the event handler function cannot get the updated state object value?

這是我的代碼:

應用程序.js:

import './App.css';
import { useAlarmClock } from "./useAlarmClock";
export default function App() {
  const[action,data]=useAlarmClock();
  let start=()=>{
    action.start();
  }
  return (
    <div className="App">
      <button onClick={start}>Start Alarm Clock</button>
    </div>
  );
}

使用AlarmClock.js

import { useReducer } from "react";
import AlarmClock from './AlarmClock';
let reducer = (state, action) => {
    let result = { ...state };
    console.log(action);
    switch (action.type) {
        case "init":
            result = { "alarmClock": action.alarmClock }
            break;
        default: break;    
    }
    return result
}

export function useAlarmClock() {
    const [itemList, updateItemList] = useReducer(reducer, {});
    let start = () => {
        let alarmClock = new AlarmClock();
        alarmClock.on("connectionTimeout", () => {
            console.log(itemList);
        })
        alarmClock.start();
        updateItemList({ "type": "init", alarmClock })
    }
    return [{
        start: start
    }, {
        itemList
    }];
}

鬧鍾.js

export default class AlarmClock {
    constructor() {
        let connectionTimeoutHandler;

        /*=====================================================================*/
        /*        To configure handler for varies event                        */
        /*=====================================================================*/
        this.on = (eventType, param) => {
            switch (eventType) {
                case "connectionTimeout":
                    connectionTimeoutHandler = param;
                    break;
                default: break;
            }
        };
        this.start = () => {
            setTimeout(() => {
                connectionTimeoutHandler();
            }, 5000);
        }
    }
}

我期望以下 function 的 output:

alarmClock.on("connectionTimeout", () => {
        console.log(itemList);
    })

應該:

{
  "alarmClock":{}
}

然而實際結果如下:

{}

所以,我不知道為什么console.log output 不包含alarmClock object。

在每次渲染時,都會為 itemList 創建一個新的 object,因為它具有不變性,但是您在“connectionTimeout”回調中只有指向 itemList 的第一個實例的鏈接。 您可以使用 ref 掛鈎訪問所需版本的 itemList,因此您需要像這樣執行 smtn:

使用AlarmClock.js

 import { useReducer } from "react"; import AlarmClock from './AlarmClock'; let reducer = (state, action) => { let result = {...state }; console.log(action); switch (action.type) { case "init": result = { "alarmClock": action.alarmClock } break; default: break; } return result } export function useAlarmClock() { const [itemList, updateItemList] = useReducer(reducer, {}); const itemListRef = useRef(itemList); itemListRef.current = itemList; let start = () => { let alarmClock = new AlarmClock(); alarmClock.on("connectionTimeout", () => { console.log(itemListRef.current); }) alarmClock.start(); updateItemList({ "type": "init", alarmClock }) } return [{ start: start }, { itemList }]; }

UPD:這是工作示例:

 const {useReducer, useEffect, useRef} = React; function App() { const[action,data]=useAlarmClock(); let start=()=>{ action.start(); } return ( <div className="App"> <button onClick={start}>Start Alarm Clock</button> </div> ); } let reducer = (state, action) => { let result = {...state }; console.log(action); switch (action.type) { case "init": result = { "alarmClock": action.alarmClock } break; default: break; } return result } function useAlarmClock() { const [itemList, updateItemList] = useReducer(reducer, {}); const itemListRef = React.useRef(itemList); itemListRef.current = itemList; let start = () => { let alarmClock = new AlarmClock(); alarmClock.on("connectionTimeout", () => { console.log(itemListRef.current); }) alarmClock.start(); updateItemList({ "type": "init", alarmClock }) } return [{ start: start }, { itemList }]; } class AlarmClock { constructor() { let connectionTimeoutHandler; /*=====================================================================*/ /* To configure handler for varies event */ /*=====================================================================*/ this.on = (eventType, param) => { switch (eventType) { case "connectionTimeout": connectionTimeoutHandler = param; break; default: break; } }; this.start = () => { setTimeout(() => { connectionTimeoutHandler(); }, 5000); } } } ReactDOM.render(<App />, document.getElementById("root"))
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script> <div id="root"></div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM