【发布时间】:2022-01-03 08:26:08
【问题描述】:
简介
我正在处理我的应用程序中的所有错误。我注意到 React 可以处理不同类型的错误...
-
渲染错误(未定义的道具,...),可以使用 Error Boundary Component 和自定义后备组件来处理。
-
来自后端的错误,我想用 i18n.js 在 toast 中显示以翻译消息。
在 React 应用程序中结合这两种类型的错误处理是否常见?
在 toast 中显示错误
我决定创建自己的React Context,它会为通知、错误等呈现toast。这是我的实现:
/* eslint-disable react/prop-types */
import React, {
createContext,
useReducer,
useMemo,
} from "react";
import toastReducer, {
initialState,
actionCreators,
} from "./helpers/reducers/toastReducer";
import { TOAST_TYPES, DEFAULT_TOAST_DURATION } from "../../utils/toast";
import Toast from "../../components/Toast";
const ToastContext = createContext(null);
export default ToastContext;
export function ToastProvider({ children }) {
const [toast, dispatch] = useReducer(toastReducer, initialState);
const open = (
type = TOAST_TYPES[0],
message,
duration = DEFAULT_TOAST_DURATION,
action = undefined
) => {
dispatch(actionCreators.open(type, message, duration, action));
};
const close = () => {
dispatch(actionCreators.close());
};
const value = useMemo(() => ({
open,
close,
}), []);
return (
<ToastContext.Provider value={value}>
{children}
<Toast
visible={toast.visible}
type={toast.type}
duration={toast.duration}
action={toast.action}
onDismiss={close}
>
{toast.message}
</Toast>
</ToastContext.Provider>
);
}
我还实现了使用此上下文的 useToast() 钩子。
从服务器获取数据
当我使用钩子时,我在每个从我的数据库中获取数据的自定义钩子上将错误保存为“错误”状态。
// Based on the library "useQuery"
const useFetchSomeData = ({ fetchOnMount = true } = {}) => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const cursor = useRef(new Date());
const isFetching = useRef(false);
const fetchData = async () => {
if (isFetching.current) return;
isFetching.current = true;
setLoading(true);
try {
const data = await api.fetchData(cursor.current);
} catch(err) {
setError(err);
} finally {
setLoading(false);
isFetching.current = false;
}
}
useEffect(() => {
if (fetchOnMount) {
fetchData();
}
}, []);
return {
data,
loading,
error,
fetchData
}
}
在我的组件中我只是这样做:
const { data, error, loading } = useFetchData();
const toast = useToast();
const { t } = useI18N();
useEffect(() => {
if (error) {
toast.open("error", t(err.code));
}
}, [error, t]);
问题
-
如您所见,在我的组件中,我只是使用
useEffect将翻译后的错误发送到我的 toast 上下文。但是......如果我从服务器两次收到相同的错误响应怎么办?我的意思是,错误没有在自定义钩子中重置为null...我该怎么做? -
这种实现是否健壮(在您看来)并且在这些情况下很典型?
【问题讨论】:
-
当我得到一个对象作为响应时,如果我只是跳过自定义钩子中的错误重置不会有问题......因为对象引用本身会有所不同(不是内容),但是想象一下错误的类型是一个字符串......那么我的组件的useEffect将不会被重新执行(因为dep没有改变)。
标签: reactjs react-native error-handling react-hooks try-catch