在装入实际对象之前,使用Axios和useEffect获取数据将导致null。
不幸的是,在实际对象不为空之前,我无法使用对象分解。
我被迫使用钩子检查对象是否为空。
例如,我想创建多个函数并将我的代码拆分为单独的函数,以提高可读性。
这是我的HTTP请求挂钩:
import { useState, useEffect } from 'react';
import axios from 'axios';
export const useHttp = (url, dependencies) => {
const [isLoading, setIsLoading] = useState(false);
const [fetchedData, setFetchedData] = useState(null);
useEffect(() => {
setIsLoading(true);
axios
.get(url)
.then(response => {
setIsLoading(false);
setFetchedData(response.data);
})
.catch(error => {
console.error('Oops!', error);
setIsLoading(false);
});
}, dependencies);
return [isLoading, fetchedData];
};
接着是我的页面组件:
import React from 'react';
import { PAGE_ABOUT, API_URL } from 'constants/import';
import Header from './sections/Header';
import Main from './sections/Main';
import Aside from './sections/Aside';
import { useHttp } from 'hooks/http';
const About = () => {
const [isLoading, about] = useHttp(PAGE_ABOUT, []);
if (!isLoading && about) {
return (
<section className="about">
<div className="row">
<Header
featuredImage={API_URL + about.page_featured_image.path}
authorImage={API_URL + about.page_author_image.path}
authorImageMeta={about.page_author_image.meta.title}
title={about.about_title}
subtitle={about.about_subtitle}
/>
<Main
title={about.page_title}
content={about.page_content}
/>
<Aside
title={about.about_title}
content={about.about_content}
/>
</div>
</section>
);
}
};
export default React.memo(About);
实际问题是我无法在实际返回对象之前嵌套函数。
有没有一种方法可以不经检查就获取数据?或更清洁的解决方案会有所帮助。
我想使用多个组件来拆分代码。
任何建议或建议将不胜感激。
答案 0 :(得分:7)
您的要求对UI不利。在获取数据时,您不想阻止UI呈现。因此,通常的做法是显示“正在加载”微调框,或者(如果您指望的是快速的请求,则不显示任何内容,直到它弹出。)
所以您会得到类似的东西
const About = () => {
const [isLoading, about] = useHttp(PAGE_ABOUT, []);
if (isLoading) return null; // or <Loading />
return (
<section className="about">
<div className="row">
<Header
featuredImage={API_URL + about.page_featured_image.path}
authorImage={API_URL + about.page_author_image.path}
authorImageMeta={about.page_author_image.meta.title}
title={about.about_title}
subtitle={about.about_subtitle}
/>
<Main
title={about.page_title}
content={about.page_content}
/>
<Aside
title={about.about_title}
content={about.about_content}
/>
</div>
</section>
);
};
如果您的api无法保护错误,并且您担心自己被空或未定义,则可以使用Error Boundary组件包装该组件,然后显示默认错误。但这取决于您是否在应用程序中使用它们。
错误边界是捕获JavaScript错误的React组件 在其子组件树的任何位置,记录这些错误并显示 后备UI,而不是崩溃的组件树。错误 边界在渲染期间,生命周期方法以及 它们下面整棵树的构造函数。
答案 1 :(得分:0)
如果您在我们的关于组件中的条件为假,则不会返回任何消息,因此,如果正在加载或关于,请添加一个案例装载机也许:
const About = () => {
const [isLoading, about] = useHttp(PAGE_ABOUT, []);
let conditionalComponent = null;
if (!isLoading && about) {
conditionalComponent= (
<section className="about">
<div className="row">
<Header
featuredImage={API_URL + about.page_featured_image.path}
authorImage={API_URL + about.page_author_image.path}
authorImageMeta={about.page_author_image.meta.title}
title={about.about_title}
subtitle={about.about_subtitle}
/>
<Main
title={about.page_title}
content={about.page_content}
/>
<Aside
title={about.about_title}
content={about.about_content}
/>
</div>
</section>
);
}
return conditionalComponent
};
答案 2 :(得分:0)
据我所知,您想摆脱条件if (!isLoading && about) {
您可以通过多种方式实现它:
1)您可以自己创建Conditional
组件。此组件应接收children
道具作为函数,并且应将其他道具应用于此函数:
function Conditional({ children, ...other }) {
if (Object.entries(other).some(([key, value]) => !value)) {
return "empty"; // null or some `<Loading />` component
}
return children(other);
}
我也做了一个小型演示https://codesandbox.io/s/upbeat-cori-ngenk
它可以帮助您仅创建一个条件条件并将其在数十个组件中重复使用:)
2)您可以使用一些库,该库建立在React.lazy和React.Suspense的顶部(但是在服务器端不起作用)。 例如https://dev.to/charlesstover/react-suspense-with-the-fetch-api-374j和一个库:https://github.com/CharlesStover/fetch-suspense