在反应中动态渲染子组件

Dynamically rendering child components in react

我正在使用 firestore 数据库将我的数据存储在集合“listings”中。因此,对于“列表”中的每个文档,我需要使用每个文档中的数据在 Home.js 中呈现一个 <BookListing/> 元素。根据我的研究,还有其他一些与此类似的问题,但它们已经过时并且使用了不同的反应语法。这是我的代码:

function BookListing({id, ISBN, title, image, price}) {
    
    return (
        <div className="bookListing">
            <div className='bookListing_info'>
                <p className="bookListing_infoTitle">{title}</p>
                <p className="bookListing_infoISBN"><span className="bookListing_infoISBNtag">ISBN: </span>{ISBN}</p>
                <p className="bookListing_infoPrice">
                    <small>$</small>
                    {price}
                </p>
            </div>
            <img className="bookListing_img" src={image} alt=""></img>
            <button className="bookListing_addToCart">Add to Cart</button>
        </div>
    )
}

export default BookListing

function Home() {

    document.title ="Home";

    useEffect(() => {
        getDocs(collection(db, 'listings'))
        .then(queryCollection => {
            queryCollection.forEach((doc) => {
                console.log(doc.id, " => ", doc.data());
                const element = <BookListing id="456" ISBN="0101" title="sample_title" image="https://nnpbeta.wustl.edu/img/bookCovers/genericBookCover.jpg" price="25"/>;
                ReactDOM.render(
                    element,
                    document.getElementById('home-contents-main')
                );
            })
        });
    }, []);



    return (
        <div className="home">
            <div className="home_container">
                <div id="home-contents-main" className="home_contents">
                </div>
            </div>
        </div>
    )
}
export default Home

您可以创建一个可重用组件,将数据传递给它,然后使用 map() 对其进行迭代。定义一个状态,并在 useEffect 中使用它,而不是创建元素并使用状态作为数据属性处理过程。

function BookListing({ id, ISBN, title, image, price }) {
  return (
    <div className="bookListing">
      <div className="bookListing_info">
        <p className="bookListing_infoTitle">{title}</p>
        <p className="bookListing_infoISBN">
          <span className="bookListing_infoISBNtag">ISBN: </span>
          {ISBN}
        </p>
        <p className="bookListing_infoPrice">
          <small>$</small>
          {price}
        </p>
      </div>
      <img className="bookListing_img" src={image} alt=""></img>
      <button className="bookListing_addToCart">Add to Cart</button>
    </div>
  );
}

function Home() {
  const [data, setData] = useState([]);

  useEffect(() => {
    document.title = 'College Reseller';
    getDocs(collection(db, 'listings')).then((queryCollection) => setData(queryCollection));
  }, []);

  return (
    <div className="home">
      <div className="home_container">
        <div id="home-contents-main" className="home_contents">
          {data.map((doc) => (
            <BookListing
              id="456"
              ISBN="0101"
              title="sample_title"
              image="https://nnpbeta.wustl.edu/img/bookCovers/genericBookCover.jpg"
              price="25"
            />
          ))}
        </div>
      </div>
    </div>
  );
}
export default Home;

最好(也是最常见的)将任务分为两部分:异步获取数据(在您的情况下来自 firestore),并将该数据映射到要在屏幕上显示的 React 组件。

一个例子:

function Home() {
  // A list of objects, each with `id` and `data` fields.
  const [listings, setListings] = useState([]) // [] is the initial data.

  // 1. Fetching the data

  useEffect(() => {
    getDocs(collection(db, 'listings'))
      .then(queryCollection => {
        const docs = [];
        queryCollection.forEach((doc) => {
          docs.push({
            id: doc.id,
            data: doc.data()
          });

          // Update the listings with the new data; this triggers a re-render
          setListings(docs);
        });
      });
  }, []);

  // 2. Rendering the data

  return (
    <div className="home">
      <div className="home_container">
        <div className="home_contents">
          {
            listings.map(listing => (
              <BookListing
                id={listing.id}
                ISBN={listing.data.ISBN}
                title={listing.data.title}
                image={listing.data.image}
                price={listing.data.price}
              />
            ))
          }
        </div>
      </div>
    </div>
  );
}

一些提示:

  • 从其他网络服务器或服务获取数据可以而且通常以相同的方式完成。
  • 这个例子在现代 JS 语法的优雅方面可以改进很多,我试图保持简单。
  • 在大多数情况下,您不想直接使用 ReactDOM(仅用于应用程序的入口点),或者手动乱用 DOM; React 会为您处理!
  • 如果您不熟悉 useState 挂钩,请阅读 React 文档中的 Using the State Hook。很重要!