如果该函数在挂钩之外调用
我有一个问题,我不知道如何解决。
基本上,我的想法是,我有一个只需要实例化一次的类(实例化是在 useMemo 中完成的,以便只完成一次),这个类实际上是一个调用处理程序的 websocket 实现(此处为 onCounterChanged)当它从后端接收到消息时),以便更新组件状态,但由于某种原因该处理程序保留旧的计数器状态值。这是代码:
class MyService {
constructor(onCounterChange) {
this.onCounterChange = onCounterChange;
}
start = () => {
//This setInterval is only used to try to reproduce the reality (an async event so for example
//when a message is received from the server). So i call this onCounterChange every 2 sec to
//simulate a message received from the server
setInterval(() => {
this.onCounterChange();
}, 2000);
};
}
const MyComponent = () => {
const [counter, setCounter] = React.useState(0);
const onCounterChanged = () => {
console.log("onCounterChanged", counter);
setCounter(counter + 1);
};
//i'm using useMemo in order to keep the instance of MyService, because i'm doing some stuff
//(connect to the webSocket etc... in this class, i don't want to create an new instance on every
//render and do the connection to the server again
const myService = React.useMemo(() => new MyService(onCounterChanged), []);
React.useEffect(() => {
myService.start();
}, []);
return <div>{counter}</div>;
};
这是一个沙箱,可以查看发生了什么: https://codesandbox.io/s/blazing-tree -z1m99e?file=/src/App.js
您可以看到计数器没有递增,函数 onCounterChange 每秒都会调用一次,但计数器状态不会在该函数内部更新处理程序。我尝试使用 useCallback 修复它,但没有任何效果。
知道如何解决这个问题吗?我不是反应专家,所以如果我遗漏了什么,抱歉。
感谢您的阅读。
I have an issue and i don't know how to solve it.
Basically, the idea is that i have a class that i need to instanciate only once (instanciation is done in an useMemo in order to have it done only once), this class is in reality a websocket implementation which calls a handler (here onCounterChanged) when it receives a message from the backend), in order to update a component state, but for some reason this handler holds the old counter state value. Here is the code :
class MyService {
constructor(onCounterChange) {
this.onCounterChange = onCounterChange;
}
start = () => {
//This setInterval is only used to try to reproduce the reality (an async event so for example
//when a message is received from the server). So i call this onCounterChange every 2 sec to
//simulate a message received from the server
setInterval(() => {
this.onCounterChange();
}, 2000);
};
}
const MyComponent = () => {
const [counter, setCounter] = React.useState(0);
const onCounterChanged = () => {
console.log("onCounterChanged", counter);
setCounter(counter + 1);
};
//i'm using useMemo in order to keep the instance of MyService, because i'm doing some stuff
//(connect to the webSocket etc... in this class, i don't want to create an new instance on every
//render and do the connection to the server again
const myService = React.useMemo(() => new MyService(onCounterChanged), []);
React.useEffect(() => {
myService.start();
}, []);
return <div>{counter}</div>;
};
Here is a sandbox to see what's happening :
https://codesandbox.io/s/blazing-tree-z1m99e?file=/src/App.js
You can see that the counter isn't incremented, the function onCounterChange is called every seconds but the counter state is not updated inside of that handler. I tried to fix it by using useCallback but nothing was working.
Any idea how can i fix this ? I'm not a pro of react so, sorry if i'm missing something.
Thanks for reading.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的更新状态存在问题,我做了一些重构。
当您尝试使用旧值更新状态时,您应该使用回调而不是传递“当前”值,避免传递当前状态值,因为它并不总是与实际状态值同步
使用回调将确保您正在使用最新值
这是一个 CodeSandbox: https://codesandbox.io/s/goofy-sanderson-bfq3mh?file=/src/App.js
There is an issue with your update state, I did a little refactor.
When you try to update the state using the old value, you should use a callback instead of passing the "current" value, avoid passing the current state value because is not always in sync with the actual state value
Using a callback will assure you that is using the latest value
Here is a CodeSandbox: https://codesandbox.io/s/goofy-sanderson-bfq3mh?file=/src/App.js