将子组件传递给 API 组件

时间:2021-04-03 10:41:39

标签: reactjs

我正在尝试将 API fetcher 实现为可重用组件,以减少重复代码。

如何将子组件传递给此 ApiFetcher,以便它呈现特定子组件而不是硬编码组件?

此外,我的 CompanyProfile 组件是否以有效的方式编码或是否有优化空间?

import React from "react";
import { useState, useEffect } from "react";

function ApiFetcher(props) {
  const [error, setError] = useState(null);
  const [isLoaded, setIsLoaded] = useState(false);
  const [items, setItems] = useState([]);

  useEffect(() => {
    fetch(props.url)
      .then((res) => res.json())
      .then(
        (result) => {
          setIsLoaded(true);
          setItems(result);
        },
        (error) => {
          setIsLoaded(true);
          setError(error);
        }
      );
  }, []);

  if (error) {
    return <div>Error: {error.message}</div>;
  } else if (!isLoaded) {
    return <div>Loading...</div>;
  } else {

    // TODO: return props.childrend instead of hard coded component

    return (
      <div>
        <CompanyProfile items={items} />
      </div>
    );
  }
}

function CompanyProfile(props) {
  return (
    <div>
      <ul>
        {props.items.map((item) => (
          <li key={item.symbol}>
            {item.companyName} {item.price}
          </li>
        ))}
      </ul>
    </div>
  );
}

function App() {
  const apiUrl =
    "https://financialmodelingprep.com/api/v3/profile/AAPL?apikey=demo";

  // TODO: implement children of ApiFetcher
  return (
    <div>
      <ApiFetcher url={apiUrl}>
      </ApiFetcher>
    </div>
  );
}

export default App;

2 个答案:

答案 0 :(得分:1)

您可以使用高阶组件。

<块引用>

高阶组件(HOC)是 React 中的一种高级技术,用于 重用组件逻辑。 HOC 本身不是 React API 的一部分。 它们是从 React 的组合性质中产生的一种模式。

示例:

function withApiResponse(WrappedComponent, url, ...) {
 return function ApiFetcher(props) {
  ...
  const someData = ...;
  const items = ...;
  return (
      <div>
        <WrappedComponent someData/>
        <CompanyProfile items={items} />
      </div>
  );
 }
}

const Comments = withApiResponse(CommentsComponent, "/comments");
const Reviews = withApiResponse(ReviewsComponent, "/reviews");

function App() {
  return (
    <div>
      <Comments />
      <Reviews />
    </div>
  );
}

答案 1 :(得分:1)

您可以提供一个函数作为 ApiFetcher 的唯一子函数,并在加载数据后调用它:

<ApiFetcher url={apiUrl}>
  {(items) => {
    return <CompanyProfile items={items} />;
  }}
</ApiFetcher>

然后在 ApiFetcher 中:

  if (error) {
    return <div>Error: {error.message}</div>;
  } else if (!isLoaded) {
    return <div>Loading...</div>;
  } else {
    // Call the provided function
    return props.children(items);
  }