【问题标题】:Fetching data from Firebase and storing in local state is undefined从 Firebase 获取数据并存储在本地状态是未定义的
【发布时间】:2022-01-18 13:43:53
【问题描述】:

我正在从 firebase 获取数据,但结果未定义。当我注释掉使用数据的元素时,数据以状态存储,我取消注释元素并且它们呈现没有任何问题。当我进行更改并保存文件时,它会恢复为未定义并且元素不会呈现。

这是我目前正在使用的代码:

  const router = useRouter();
  const { make, model, id } = router.query;
  const [singleCar, setSingleCar] = useState([]);

  const docRef = doc(db, "car listings", `${id}`);

  useEffect(() => {
    const fetchDetails = async () => {
      await getDoc(docRef).then((doc) => {
        const carData = doc.data();
        setSingleCar(carData);
      });

      await onSnapshot(docRef, (doc) => {
        const carData = doc.data();
        setSingleCar(carData);
      });
    };
    fetchDetails();
  }, [singleCar]);

我知道我既要获取一个文档又要添加一个实时侦听器,但我不确定哪个是最好的操作,因为 getDoc 方法在获取文档后只运行一次,所以我认为它可能会更好也有一个实时监听器。

这是我正在渲染的内容,我的想法是,如果状态未定义,则渲染 Loader 组件,直到状态随着适当的数据而改变。

{singleCar === [] ? (
        <Loader />
      ) : (
        <Container maxW="container.xl">
          <Box display="flex" justifyContent="space-around">
            <Image
              w="500px"
              src={singleCar.carImages[0].fileURL}
              borderRadius="10px"
            />

            {/* <CarImageGalleryModal isOpen={isOpen} onClose={onClose} /> */}
            <Box
              display="flex"
              flexDirection="column"
              justifyContent="space-between"
            >
              <SingleCarPrimary
                make={singleCar.carDetails.make}
                model={singleCar.carDetails.model}
                year={singleCar.carDetails.year}
                doors={singleCar.carDetails.doors}
                engineSize={singleCar.carDetails.engine_size}
                fuelType={singleCar.carDetails.fuel_type}
                body={singleCar.carDetails.year}
                price={singleCar.carPrice}
              />
              <ContactSection />
            </Box>
          </Box>
          <CarSummary carDetails={singleCar.carDetails} />
          <SingleCarDescription carDescription={singleCar.carDescription} />
        </Container>
      )}

以下是信息在 Firebase 中的存储方式,让您了解正在检索的数据。

后端:Firebase 版本 9 前端:Next.js / Chakra UI

【问题讨论】:

    标签: firebase next.js


    【解决方案1】:

    我能够使用 getServerSideProps 的方法来解决这个问题,我认为这消除了对 useEffect 的需要。

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案2】:

    问题应该是查询的文档标识符未引用任何文档,因此您将获得 undefined 属性结果。

    这里列出了您应该应用于您的实施以缓解此类问题的修复列表。

    您最好使用单独的loading 状态,该状态将在加载数据后重置,以便它可以反映加载和清空结果:

      const router = useRouter();
      const { make, model, id } = router.query;
      const [singleCar, setSingleCar] = useState({}); // the car should be an object and not an array
      const [loading, setLoading] = useState(true);
    
      const docRef = doc(db, "cars", `${id}`); // avoid spaces in document names
    
      useEffect(() => {
        const fetchDetails = async () => {
          await getDoc(docRef).then((doc) => {
            setLoading(false);
            if (doc.exists()) {
              setSingleCar(doc.data());
            }
          });
        };
        // fetch the `car` data
        fetchDetails();
        // then attach the change listener
        await onSnapshot(docRef, (doc) => {
          const carData = doc.data();
          setSingleCar(carData);
        });
      }, []); // you should not rerun the effect on state changes as this will keep on reattaching state listener again and again and may fall into endless fetching loops
    

    然后您的组件声明可能会更新如下(您可能仍需要更新它以反映空车状态 => 已获取数据但没有反映查询id 的汽车):

    {loading === true ? (
        <Loader />
      ) : (
        <Container maxW="container.xl">
          <Box display="flex" justifyContent="space-around">
            <Image
              w="500px"
              src={singleCar.carImages[0].fileURL}
              borderRadius="10px"
            />
    
            {/* <CarImageGalleryModal isOpen={isOpen} onClose={onClose} /> */}
            <Box
              display="flex"
              flexDirection="column"
              justifyContent="space-between"
            >
              <SingleCarPrimary
                make={singleCar.carDetails.make}
                model={singleCar.carDetails.model}
                year={singleCar.carDetails.year}
                doors={singleCar.carDetails.doors}
                engineSize={singleCar.carDetails.engine_size}
                fuelType={singleCar.carDetails.fuel_type}
                body={singleCar.carDetails.year}
                price={singleCar.carPrice}
              />
              <ContactSection />
            </Box>
          </Box>
          <CarSummary carDetails={singleCar.carDetails} />
          <SingleCarDescription carDescription={singleCar.carDescription} />
        </Container>
      )}
    

    【讨论】:

    • 我似乎仍然不确定,所以正如你所说,id 可能有问题。奇怪的是,例如,最近当我在控制台日志中添加时,所有数据都被毫无问题地获取并呈现到页面上。您认为最好将 docRef 放在 useEffect 中吗?
    • 好的,所以我将 docRef 添加到 useEffect(在 fetchDetails 函数外部和内部),没有区别。它正在记录正确的 id,但 doc 方法似乎无法识别它
    猜你喜欢
    • 2018-02-24
    • 2021-01-12
    • 1970-01-01
    • 2019-09-09
    • 1970-01-01
    • 2014-10-28
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多