来自 useState 钩子的 React setState 在传递给 RxJS 订阅的回调中使用时会导致异常



我正在编写一些帮助程序来简化 React 中 RxJS 的使用。

我编写了一个自定义钩子,它允许您发送回调以订阅并从 RxJS 流中获取更新并更新它。此挂钩还允许您注册流错误和完成的回调。 这些在测试中工作正常,但是在编写适当的示例时,React 会在流错误、应该处理的错误以及 UI 中显示的消息时抛出错误。

这是一个工作沙箱,代码与下面相同,带有用于更新、发送错误和完成流的按钮

演示组件如下。请注意发生错误的行:

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>
);
}

自定义钩子如下:

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];
};

来自 React 的错误消息不是很有用,如果我理解正确,错误边界只会帮助我显示更好的 UI,但我有兴趣修复错误,而不是包含它。

更新状态的行被注释掉后,回调工作并记录到控制台没有问题,而如果我在回调中更新状态(以便我可以驱动 UI 更新(,它会崩溃。 我尝试了许多解决方法并在钩子和组件之间转移响应,但最终我确实需要更新组件中的状态,这导致了崩溃。 奇怪的是,完成流也会通过非常相似的回调更新状态,但那个回调有效。

我做错了什么?可以提供帮助或解决吗?

在 RxJS 中,任何错误或完整调用基本上都会"杀死"流。setHasError(true)"Sample"组件后,它会重新呈现并再次运行以下行:

const [val, setVal] = useSubject(subject, onError, onComplete);

该钩子的开头是:

const [value, setValue] = useState(subject.getValue());

其中,错误主题上的 getValue(( 会引发错误。

最新更新