[英]React setState from useState hook causes exception when used in callback passed to RxJS subsciption
I'm writing some helpers to ease usage of RxJS within React.我正在编写一些帮助程序来简化 React 中 RxJS 的使用。
I wrote a custom hook which allows you to send callbacks to subscribe and get updates from an RxJS stream and update it.我编写了一个自定义钩子,它允许您发送回调以订阅并从 RxJS 流中获取更新并更新它。 This hook also lets you register callbacks for stream error and completion .
这个钩子还允许你注册流错误和完成的回调。 These worked properly in tests, but when writing a proper example, React throws an error on stream error, error which should be handled and the message displayed in the UI.
这些在测试中工作正常,但是在编写正确的示例时,React 会在流错误、应该处理的错误和 UI 中显示的消息上引发错误。
This is a working sandbox with the same code as below, with buttons for updating, sending an error and completing the stream这是一个工作沙箱,代码与下面相同,带有用于更新、发送错误和完成流的按钮
demo component follows.演示组件如下。 Note the line where the error happens:
请注意发生错误的行:
export default ({subject})=>{
const [hasError, setHasError] = useState(false);
const [complete, setComplete] = useState(false);
const onError = (err)=>{
setHasError(true); // <-------------- Commenting this line avoids the error!
console.log('Value handled error',err);
};
const onComplete = ()=>{
setComplete(true);
console.log('Value handled completion');
};
const [val,setVal] = useSubject(subject,onError,onComplete);
const onClick = ()=>setVal(val+1);
return (
<span>
{val}
{hasError?' An Error ocurred ':null}
{complete?' Stream has completed ':null}
<button onClick={onClick}>increment</button>
<button onClick={()=>subject.error(5)}>Generate error</button>
<button onClick={()=>subject.complete()}>Complete</button>
</span>
);
}
Custom hook follows:自定义钩子如下:
export const useSubject = (subject,onError,onComplete) => {
const [value, setValue] = useState(subject.getValue());
useEffect(() => {
const subFn = { next: data => setValue(data) };
if (onError) { subFn.error = err => onError(err); }
if (onComplete) { subFn.complete = () => onComplete(); }
const sub = subject.pipe(skip(1)).subscribe(subFn);
return () => sub.unsubscribe();
});
const newSetState = state => subject.next(state);
return [value, newSetState];
};
The error message from React is not very useful, and if I understand correctly, error boundaries would only help me display a better UI, but I'm interested in fixing the error, not containing it. React 的错误消息不是很有用,如果我理解正确,错误边界只会帮助我显示更好的 UI,但我有兴趣修复错误,而不是包含它。
With the line that updates the state commented out, the callback works and logs to console with no issue, while if I update the state in the callback (so I can drive an UI update), it crashes.注释掉更新状态的行后,回调可以正常工作并记录到控制台,没有问题,而如果我更新回调中的状态(以便我可以驱动 UI 更新),它就会崩溃。 I tried many workarounds and shifting responsabilities between hook and component, but in the end I do need the state updated in the component, which is causing the crash.
我尝试了许多解决方法并在钩子和组件之间转移责任,但最终我确实需要在组件中更新状态,这导致了崩溃。 Strangely enough, completing the stream also updates the state, via a very similar callback, but that one works.
奇怪的是,完成流也会更新状态,通过一个非常相似的回调,但那个是有效的。
What am I doing wrong?我究竟做错了什么? Can it be helped or worked around?
它可以得到帮助或解决吗?
In RxJS any error or complete-call will basically "kill" a stream.在 RxJS 中,任何错误或完整调用基本上都会“杀死”一个流。 After you
setHasError(true)
in your "Sample" component, it re-renders and runs this line again:在“示例”组件中
setHasError(true)
后,它会重新渲染并再次运行此行:
const [val, setVal] = useSubject(subject, onError, onComplete);
that hook begins with:该钩子以:
const [value, setValue] = useState(subject.getValue());
Where getValue() on an errored subject throws an error.错误主题上的 getValue() 在哪里引发错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.