简体   繁体   English

为什么事件处理程序 function 无法获取更新后的 state object 值?

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

Here is my code:这是我的代码:

App.js:应用程序.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>
  );
}

useAlarmClock.js使用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
    }];
}

AlarmClock.js闹钟.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);
        }
    }
}

I expect the output of the following function:我期望以下 function 的 output:

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

should be:应该:

{
  "alarmClock":{}
}

However the actual result is as the following:然而实际结果如下:

{}

So, I don't know why the console.log output does not contain the alarmClock object.所以,我不知道为什么console.log output 不包含alarmClock object。

At each render a new object for itemList is created due immutability, but you have only link to the first instance of itemList in your 'connectionTimeout' callback.在每次渲染时,都会为 itemList 创建一个新的 object,因为它具有不变性,但是您在“connectionTimeout”回调中只有指向 itemList 的第一个实例的链接。 You can access needed version of itemList with ref hook, so you need to do smtn like this:您可以使用 ref 挂钩访问所需版本的 itemList,因此您需要像这样执行 smtn:

useAlarmClock.js使用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: here is working example: 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