简体   繁体   English

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

[英]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.

相关问题 反应 useState 钩子,用 function 调用 setState - React useState hook, calling setState with function React useState hook 导致无限渲染 - React useState hook causes infinite rendering 在 UseState 中使用 prevState 回调 function 反应 Hook - Using prevState Callback function in UseState react Hook React hook,使用useState时的连线问题,而如果使用setState可以正常工作,如何解决 - React hook, wired issue when use useState, while if use setState work perfectly, how to solve it 在 setState 上使用 JavaScript Date 对象时,React hook useState 不更新 UI - React hook useState not updating the UI when using JavaScript Date object on setState 不能在回调中调用 React Hook “useState” - React Hook “useState” cannot be called inside a callback 何时在 React 中使用 setState 钩子 - When to use setState hook in React 使用useState挂钩的react组件是否会重新渲染每个setState调用? - Does a react component using useState hook rerender every `setState` call? HandleChange/setState 在迁移以响应 useState 挂钩后停止工作 - HandleChange/setState stopped working after migrating to react useState hook 当使用 setState function 作为 useEffect 中的参数时,为什么不需要编写回调 - When using a setState function from useState as argument in useEffect why it is not required to write a callBack
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM