Реагируйте useEffect для однократного получения данных из хранилища - PullRequest
0 голосов
/ 13 апреля 2020

Я пытаюсь выяснить, как использовать реакцию useEffect для получения данных из хранилища.

Это моя текущая попытка.

import React, { useHook, useEffect, useState } from 'react';
import {
    useParams
  } from 'react-router-dom';

import Firebase from "../../../firebase";

 const ReadBlogPost = async () => {
    const [loading, setLoading] = useState(true);
    const [currentPost, setCurrentPost] = useState([]);
    let { slug } = useParams();


      useEffect(()  =>  {
          Firebase
          .firestore
          .collection("blog")
          .doc(slug)
          .get()
          .then(function(doc) {
            if (doc.exists) {
                // setCurrentPost(doc.data());
                console.log("Document data:", doc.data());
            } else {
                // doc.data() will be undefined in this case
                console.log("No such document!");
            }
          })
          .catch(function(error) {
            console.log("Error getting document:", error);
        }), []
      })

    return (
        <div>

                    {currentPost.title}


        </div>
    )

};
export default ReadBlogPost;

Пустой массив в конце является попыткой чтобы попытаться убедиться, что реакция не использует все разрешения на чтение в хранилище, которые были подробно описаны в этой публикации и этой проблеме .

Когда я пытаюсь это сделать, Я получаю сообщение об ошибке:

Строка 19:11: ожидал присваивания или вызова функции и вместо этого увидел выражение no-unused-expressio

Файл jsx , Я видел этот пост и этот , что означает, что я должен преобразовать оператор if в троичное условие.

Моя попытка изменить это на троичное выражение:

useEffect(()  =>  {
          Firebase
          .firestore
          .collection("blog")
          .doc(slug)
          .get()
          .then(function(doc) {
            doc.exists? setCurrentPost(doc.data()) :  console.log("No such document!")
          })
          .catch(function(error) {
            console.log("Error getting document:", error);
        }), []
      })

Когда я пытаюсь это сделать, я получаю то же сообщение об ошибке, что и при использовании оператора if.

Может ли кто-нибудь помочь с примером использования useEffect для чтения данных пожарного хранилища ( один раз) в файле jsx?

СЛЕДУЮЩАЯ ПОПЫТКА Используя предложение Николаса, я изменил useEffect на:

useEffect(()  =>  {
          Firebase
          .firestore
          .collection("blog")
          .doc(slug)
          .get()
          .then(function(doc) {
            doc.exists? setCurrentPost(doc.data()) :  console.log("No such document!")
          .catch(function(error) {
                console.log("Error getting document:", error)
          })  
        }, [])
      })

Это приводит к ошибке, которая говорит:

Ошибка: объекты недопустимы как дочерние элементы React (найдено: [обещание объекта]). Если вы хотите визуализировать коллекцию дочерних элементов, используйте вместо этого массив.

СЛЕДУЮЩАЯ ПОПЫТКА

Я попробовал предложение Бена - изменить объект в currentPost обратно на массив, но я получаю ту же ошибку, что и я, когда пытаюсь предложить предложение Николаса.

Затем я попытался объединить их биты так:

import React, { useHook, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';

import Firebase from "../../../firebase";

const ReadBlogPost = async () => {
    let { slug } = useParams();
    const [loading, setLoading] = useState(true);
    const [currentPost, setCurrentPost] = useState([]);



    useEffect(() => {

        const fetchData = async() => {

            try {
                const response = await Firebase.firestore
                    .collection("blog")
                    .doc(slug)
                    .get()
                    .then(function(doc) {
                        doc.exists? setCurrentPost(doc.data()) :  console.log("No such document!")


                    }) 
                } catch(err) {
                    console.error(err);
                }   
            };         


        fetchData();

    }, []);


    return (
        <div>

            {!loading && 
currentPost.title}


        </div>
    )

};
export default ReadBlogPost;

Я все еще получаю то же самое ошибка.

Ошибка: объекты недопустимы как дочерний элемент React (найдено: [обещание объекта]). Если вы хотите отобразить коллекцию дочерних элементов, используйте вместо этого массив. в ReadBlogPost (создан Context.Consumer)

Я не знаю, есть ли в этом ключ, но ссылка на ReadBlogPost предполагает, что у меня где-то есть потребитель контекста. Я еще не создал контекст - поэтому не уверен, что он ищет, чтобы можно было использовать useEffect?

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

У вас есть массив зависимостей в неправильном месте. С некоторым переформатированием, чтобы выделить проблему, вы делаете это:

  useEffect(() => {
    Firebase.firestore
      //...
      .catch(/*...*/), [];
  });

..., что технически допустимо javascript, из-за оператора запятой . Но так как это, вероятно, ошибка, ваш линтер указывает на это.

Вместо этого вы должны сделать это:

  useEffect(() => {
    Firebase.firestore
      //...
      .catch(/*...*/);
  }, []);
0 голосов
/ 13 апреля 2020

При получении данных с использованием useEffect ожидается синхронный вызов. Запрос данных из Firestore будет асинхронным, поэтому, чтобы обойти это, мы можем добавить функцию, заключающую в себе вызов firestore с именем fetchData, как показано ниже:

import React, { useHook, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import Firebase from "../../../firebase";

function ReadBlogPost () {
    const [loading, setLoading] = useState(true);
    const [currentPost, setCurrentPost] = useState({});
    let { slug } = useParams();


    useEffect(() => {

        const fetchData = async() => {

            try {

                const response = await Firebase.firestore()
                    .collection("blog")
                    .doc(slug)
                    .get();

                console.log('response', response);

                let data = { title: 'not found' };

                if (response.exists) {
                    data = response.data();
                }

                setCurrentPost(data);
                setLoading(false);

            } catch(err) {
                console.error(err);
            }

        };

        fetchData();

    }, []);

    return (
        <div>

            {!loading && currentPost.title}


        </div>
    )

};
export default ReadBlogPost;

Я предположил, что ваш currentPost может быть объектом вместо массив, который вы запрашиваете заголовок в вашем JSX тоже - и я добавил setCurrentPost после вызова Firestore в fetchData. Надеюсь, это поможет

Обновление: я изменил настройку компонента на именованный синхронный компонент (удалил констант вверху и удалил асин c), и я также отметил, что вы упомянули, что вы изменили currentPost возвращается в массив - пожалуйста, убедитесь, что это объект, поскольку вы ссылаетесь на currentPost в JSX как объект - я просто использовал код, который я написал выше, локально, используя свою собственную базу данных firestore, и успешно получил подробности из этого useEffect. Пожалуйста, попробуйте скопировать весь фрагмент выше. Если это не сработает, я бы попросил вас также вставить свой ссылочный код Firestore из ../firebase, который вы импортировали. Также, пожалуйста, постарайтесь не смешивать .then.catch с блоками try {} catch {}, так как они пытаются сделать то же самое

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...