I have a singleton class in Daemon.ts
export default class Daemon {
private static instance : Daemon;
callback : (tstring : string)=>void;
t : number;
constructor (callback: (tstring : string)=>void){
this.data = data
this.callback = callback;
this.t = 0;
window.setInterval(this.tick.bind(this), 1000)
}
public static getInstance(callback: (tstring : string)=>void){
if(!Daemon.instance){ Daemon.instance = new Daemon(callback);}
return Daemon.instance;
}
tick(){
this.t = this.t 1
this.callback(this.t.toString());
}
}
Then in a separate file, Timefeedback.tsx
, I have:
const TimeFeedback = () => {
const [time, updateSimTime] = React.useState<string>("starting string");
const updateTime = (tString : string) => {
updateSimTime(tString);
console.log(`update time called, val: ${tString}`)
}
const daemon = Daemon.getInstance(updateTime.bind(this));
return (
<div>
{time}
</div>
);
};
What I expect to happen:
- the time state is updated on each tick() from the daemon.
What actually happens:
- the callback function
updateTime
is successfully called, and the console log prints the correct values. But the setState function updateTime() What happens is I get console logs fromTimeFeedback.tsx
with the expected value oftString
printed out. But the setState functionsetSimTime
never gets called, so the text in the div remains "starting time". Why is this?
I have investigated, when calling print events inside of Daemon I get:
function() {
[native code]
}
I tried to remove the .bind(this)
inside TimeFeedback.tsx
, but nothing changes except the print instead says:
tString => {
setSimTime(tString);
console.log(`update time called, val: ${tString}`);
}
I also walked through with the debugger and updateSimTime
does get called but it has no effect.
Why is that updateSimTime
has no effect?
CodePudding user response:
No need to .bind
in the component
updateTime.bind(this)
doesn't make sense in a function component because a function component doesn't have a this
like a class component does. Your updateTime
function can be passed directly to the Daemon.getInstance
function.
You also need to remove the this.data = data
in the Daemon
constructor because there is no data
variable` (as pointed out by @Konrad in the comments).
As a best practice, I would recommend moving the code into a useEffect
hook.
const TimeFeedback = () => {
const [time, updateSimTime] = useState<string>("starting string");
useEffect(() => {
const updateTime = (tString: string) => {
updateSimTime(tString);
console.log(`update time called, val: ${tString}`);
};
Daemon.getInstance(updateTime);
}, [updateSimTime]);
return <div>{time}</div>;
};