Логику можно вынести в собственный хук. Как-то так:
const useFetch = (url, options) => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const fetchData = async () => {
try {
setIsLoading(true);
const res = await fetch(url, options);
const json = await res.json();
setData(json);
setIsLoading(false);
} catch (error) {
setError(error);
setIsLoading(false);
}
};
useEffect(() => {
fetchData();
});
return [
data,
isLoading,
error,
fetchData,
];
};
const Example = ({ slug }) => {
const [ product, isLoading, error, fetchFn ] = useFetch(`/api/product/${slug}`);
if (isLoading) return <Preloader />;
if (error) return <Error error={error} tryAgainFn={fetchFn} />;
if (!product) return <NotFound />;
return <Product product={product} />
};