这是我的代码:
App.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);
}
}
}
我期望以下函数的输出:
alarmClock.on("connectionTimeout", () => {
console.log(itemList);
})
应该是:
{
"alarmClock":{}
}
然而实际结果如下:
{}
所以,我不知道为什么console.log输出不包含alarmClock对象。
在每次渲染时,由于不变性,都会为 itemList 创建一个新对象,但您只能链接到“connectionTimeout”回调中的 itemList 的第一个实例。您可以使用 ref hook 访问所需版本的 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>