React:从 API 获取数据时在 React 中遵循 DRY
React: following DRY in React when fetching data from API
当我从 API 获取数据时,如果我得到 Ok,我将渲染组件以显示数据,
如果发生错误,我想为不同的组件显示自定义消息,并且在获取数据期间我想显示加载消息。
export default function App() {
const { data: products, loading, error } = useFetch(
"products?category=shoes"
);
if (error) return <div>Failed to load</div>;
if (loading) return <div>wait is Loading</div>;
return (
<>
<div className="content">
<section id="products">{products.map((product) =>{return <div>product.name</div>})}</section>
</div>
</>
);
}
我计划在多个组件中进行提取调用。所以,我在想如果我能把上面的逻辑写在一个地方,比如 HOC 或 Rendered Props 并重用它。
我尝试了什么:但失败了
HOC 不会工作,因为你不能在正常函数中调用钩子。它必须是一个组件。
渲染的道具不会工作,因为它给出了这个错误:
错误:渲染的挂钩比上次渲染时多。
下面是我渲染失败的道具代码
const ShowData= function ({ data: products }) {
return (
<div>
{products.map(product => {return <div>product.name</div>})}
</div>
);
};
function SearchCount({ count }) {
return <h3>Search Results: {count} items found</h3>;
}
const Wrapper = function () {
return (
<LoadingAndError
render={ShowData}
params={{ url: "products?category=shoes" }}
></LoadingAndError>
);
};
export default Wrapper;
加载和错误逻辑已移至 LoadingAndError 组件
const LoadingAndError = function (props) {
const { url } = props.params;
const { data: products, loading,error} = useFetch(url);
if (loading)
return <h1>Loading</h1>;
if (error) return <h1>Error</h1>;
return props.render({ data: products });
};
return props.render({ data: products });
此行将 props.render
作为函数调用,但您传入了一个组件。直接调用组件可能会导致您看到的错误。如果你想像这样使用 props.render
,那么你应该传入一个创建元素的函数,如下所示:
<LoadingAndError
render={(props) => <ShowData {...props} />}
params={{ url: "products?category=shoes" }}
></LoadingAndError>
或者,如果你想一直传入render={ShowData}
,那么改变loadingAndError来创建一个元素:
const loadingAndError = function (props) {
const { url } = props.params;
const { data: products, loading,error} = useFetch(url);
if (loading)
return <h1>Loading</h1>;
if (error) return <h1>Error</h1>;
const Component = props.render
return <Component data={products}/>
}
当我从 API 获取数据时,如果我得到 Ok,我将渲染组件以显示数据, 如果发生错误,我想为不同的组件显示自定义消息,并且在获取数据期间我想显示加载消息。
export default function App() {
const { data: products, loading, error } = useFetch(
"products?category=shoes"
);
if (error) return <div>Failed to load</div>;
if (loading) return <div>wait is Loading</div>;
return (
<>
<div className="content">
<section id="products">{products.map((product) =>{return <div>product.name</div>})}</section>
</div>
</>
);
}
我计划在多个组件中进行提取调用。所以,我在想如果我能把上面的逻辑写在一个地方,比如 HOC 或 Rendered Props 并重用它。
我尝试了什么:但失败了 HOC 不会工作,因为你不能在正常函数中调用钩子。它必须是一个组件。 渲染的道具不会工作,因为它给出了这个错误: 错误:渲染的挂钩比上次渲染时多。
下面是我渲染失败的道具代码
const ShowData= function ({ data: products }) {
return (
<div>
{products.map(product => {return <div>product.name</div>})}
</div>
);
};
function SearchCount({ count }) {
return <h3>Search Results: {count} items found</h3>;
}
const Wrapper = function () {
return (
<LoadingAndError
render={ShowData}
params={{ url: "products?category=shoes" }}
></LoadingAndError>
);
};
export default Wrapper;
加载和错误逻辑已移至 LoadingAndError 组件
const LoadingAndError = function (props) {
const { url } = props.params;
const { data: products, loading,error} = useFetch(url);
if (loading)
return <h1>Loading</h1>;
if (error) return <h1>Error</h1>;
return props.render({ data: products });
};
return props.render({ data: products });
此行将 props.render
作为函数调用,但您传入了一个组件。直接调用组件可能会导致您看到的错误。如果你想像这样使用 props.render
,那么你应该传入一个创建元素的函数,如下所示:
<LoadingAndError
render={(props) => <ShowData {...props} />}
params={{ url: "products?category=shoes" }}
></LoadingAndError>
或者,如果你想一直传入render={ShowData}
,那么改变loadingAndError来创建一个元素:
const loadingAndError = function (props) {
const { url } = props.params;
const { data: products, loading,error} = useFetch(url);
if (loading)
return <h1>Loading</h1>;
if (error) return <h1>Error</h1>;
const Component = props.render
return <Component data={products}/>
}