如何使用 useState 从 Firebase 检索数据?

How to retrieve data using useState from Firebase?

我的 React 组件很少 :

MainPage.jsx

import Hotels from "./Hotels";
import WelcomePage from "./WelcomePage";

import { initializeApp } from "https://www.gstatic.com/firebasejs/9.6.0/firebase-app.js";
import {
  getFirestore,
  collection,
  getDocs,
  addDoc,
} from "https://www.gstatic.com/firebasejs/9.6.0/firebase-firestore.js";
import {
  getAuth,
  signInWithEmailAndPassword,
  createUserWithEmailAndPassword,
  onAuthStateChanged,
  signOut,
} from "https://www.gstatic.com/firebasejs/9.6.0/firebase-auth.js";
import { useState } from "react";

function MainPage() {
  const [hotels, getHotels] = useState([]);

  async function fetchHotels() {
    const firebaseConfig = {
      apiKey: "AIzaSyCHr3-x82i4RcGewtRs3XQ02Ps15Vm6ukQ",
      authDomain: "webapp-48b9a.firebaseapp.com",
      projectId: "webapp-48b9a",
      storageBucket: "webapp-48b9a.appspot.com",
      messagingSenderId: "889223227604",
      appId: "1:889223227604:web:aca93f8aa7b031fdfe7341",
    };

    const app = initializeApp(firebaseConfig);
    const db = getFirestore(app);
    const querySnapshot = await getDocs(collection(db, "reviews"));
    querySnapshot.forEach((doc) => {
      hotels.push(doc.data());
    });
    console.log(hotels);
  }

  fetchHotels();

  return (
    <main className="content">
      <Hotels hotels={hotels} />
    </main>
  );
}

export default MainPage;


Hotels.jsx

import Hotel from "./Hotel";

function Hotels(props) {
  const { hotels = [] } = props;

  return (
    <div className="Hotels">
      {hotels.map((hotel, id) => (
        <Hotel key={id} {...hotel} />
      ))}
    </div>
  );
}

export default Hotels;

Hotel.jsx

function Hotel(props) {
  const { name, img, localization, stars, review, author } = props;

  return (
    <div className="Hotel_card">
      <h2 className="Hotel_name">{name}</h2>
      <img className="Hotel_img" src={img} alt="hotel_img" />
      <h3 className="Hotel_localization">{localization}</h3>
      <p className="Hotel_stars">{stars}</p>
      <p className="Hotel_review">{review}</p>
      <h5 className="Hotel_author">Wroten by {author}</h5>
    </div>
  );
}

export default Hotel;

现在没有显示任何内容,因为 Hotel.jsx 没有看到数据。 console.log(hotels) in MainPage.jsx 输出这个对象

console.png

问题-如何显示数据?

我想我没有正确使用 useState 因为 Hostel.jsx 没有收到任何数据

你不能像这样传递道具:{...hotel}

试试这个:

 <div className="Hotels">
      {hotels.map((hotel, id) => (
       return <Hotel key={id} hotel={hotel} />
      ))}
    </div>

并在您的组件中获取 prop hotel 并从那里传递数据:

function Hotel(props) {
  const { hotel } = props;

  return (
    <div className="Hotel_card">
      <h2 className="Hotel_name">{hotel.name}</h2>
      <img className="Hotel_img" src={hotel.img} alt="hotel_img" />
      <h3 className="Hotel_localization">{hotel.localization}</h3>
      <p className="Hotel_stars">{hotel.stars}</p>
      <p className="Hotel_review">{hotel.review}</p>
      <h5 className="Hotel_author">Wroten by {hotel.author}</h5>
    </div>
  );
}

在 React 中,您不能直接改变状态,否则它将无法侦听状态的变化,re-render 组件也无法相应地进行变化。因此,在 fetchHotels 函数中,一旦您获取数据,您需要使用反应状态提供的 setState 方法来正确更新酒店状态:

const _hotels = [];
querySnapshot.forEach((doc) => {
 _hotels.push(doc.data());
});
getHotels(_hotels); //change the name of the method to setHotels to be more explicative

首先你喊出 fetchHotels()useEffect:

替换

fetchHotels();

useEffect(() => {
   fetchHotels();
}, []);

那么,你不能直接push到react状态数组,

替换

querySnapshot.forEach((doc) => {
    hotels.push(doc.data());
});

与:

let list = [];
await querySnapshot.forEach((doc) => {
   list.push(doc.data());
});
getHotels(list);

最后,你还有一个错误

<h3 className="Hotel_localization">{hotel.localization}</h3>

localization 是一个对象。 Objects are not valid as a React child

所以,应该是:

<h3 className="Hotel_localization">
    {localization._lat}, {localization._long}
</h3>

或类似的东西

演示: https://codesandbox.io/s/blissful-kate-7cmu3s