Я пишу несколько помощников для облегчения использования Rx JS в React.
Я написал настраиваемый хук , который позволяет отправлять обратные вызовы для подписки и получать обновления от Rx JS поток и обновить его. Этот хук также позволяет регистрировать обратные вызовы для ошибок потока и завершения . Они работали должным образом в тестах, но при написании правильного примера React выдает ошибку при ошибке потока, ошибку, которая должна быть обработана, и сообщение, отображаемое в пользовательском интерфейсе.
Это рабочая песочница с тот же код, что и ниже, с кнопками для обновления, отправки ошибки и завершения демонстрационного компонента
. Обратите внимание на строку, где происходит ошибка:
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 не очень полезно, и если я правильно понимаю, границы ошибок будут только помогите мне отобразить лучший пользовательский интерфейс, но я заинтересован в исправлении ошибки, не содержащей ее.
С строкой, которая обновляет состояние, закомментировано, обратный вызов работает и записывает на консоль без проблем, в то время как если Я обновляю состояние в обратном вызове (чтобы я мог управлять обновлением пользовательского интерфейса), происходит сбой. Я перепробовал много обходных путей и сдвиг ответственности между ловушкой и компонентом, но в конце мне нужно обновить состояние в компоненте, что вызывает cra sh. Как ни странно, завершение потока также обновляет состояние с помощью очень похожего обратного вызова, но этот работает.
Что я делаю не так? Это можно помочь или обойти?