Как связать представление представления из индекса с помощью ответных хуков с данными пожарного хранилища - PullRequest
0 голосов
/ 11 апреля 2020

Я пытаюсь выяснить, как определить ссылку на ссылку, которая может использовать идентификатор документа Firebase для ссылки на представление шоу для этого документа. Я могу сделать индекс. Я не могу найти способ определить ссылку на документ.

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

Я хочу попробуйте добавить ссылку в индекс, чтобы показать документ в новом представлении.

У меня есть индекс с:

  const useBlogs = () => {
const [blogs, setBlogs] = useState([]); //useState() hook, sets initial state to an empty array
  useEffect(() => {
    const unsubscribe = Firebase
      .firestore //access firestore
      .collection("blog") //access "blogs" collection
      .where("status", "==", true)
      .orderBy("createdAt")
      .get()
      .then(function(querySnapshot) {
    //   .onSnapshot(snapshot => {
        //You can "listen" to a document with the onSnapshot() method.
        const listBlogs =  querySnapshot.docs.map(doc => ({
          //map each document into snapshot
          id: doc.id, //id and data pushed into blogs array
          ...doc.data() //spread operator merges data to id.
        }));
        setBlogs(listBlogs); //blogs is equal to listBlogs
      });
    return 
    // () => unsubscribe();
  }, []);
  return blogs;
};

const BlogList = ({ editBlog }) => {
  const listBlog = useBlogs();
  return (
    <div>
      {listBlog.map(blog => (
        <Card key={blog.id} hoverable={true} style={{marginTop: "20px", marginBottom: "20px"}}>

            <Title level={4} >{blog.title} </Title>
            <Tag color="geekblue" style={{ float: "right"}}>{blog.category} </Tag>
            <Paragraph><Text>{blog.caption}

            </Text></Paragraph> 
            <Link to={`/readblog/${blog.id}`}>Read</Link>
            <Link to={`/blog/${blog.id}`}>Read</Link>
        </Card>       
      ))}
      </div>
  );
};
export default BlogList;

Тогда у меня есть маршрут, определенный с помощью:

export const BLOGINDEX = '/blog';
export const BLOGPOST = '/blog/:id';
export const NEWBLOG = '/newblog';
export const EDITBLOG = '/editblog';
export const VIEWBLOG = '/viewblog';
export const READBLOG = '/readblog/:id';    

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

Я нашел эту кодовую песочницу . Похоже, что он рендерит чистую страницу на странице updateCustomer и использует для этого данные из индекса, но этот пример слишком умен, чтобы я не мог выбрать его без объяснения того, что происходит (в частности, файл updateCustomer определяет переменную setCustomer , по ссылке на useForm - но в useForm с этим определением ничего нет. Эта переменная используется в ключевой части файла, которая пытается идентифицировать данные), поэтому я не могу имитировать c шаги.

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

Я нашел это сообщение в блоге , в котором предлагаются некоторые изменения для поиска соответствующего документа.

Я реализовал эти изменения, и пока Я могу напечатать правильный document.id на прочитанной странице, я не могу найти способ доступа к свойствам документа (например: blog.title).

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

import Firebase from "../../../firebase";
import BlogList from './View';


function ReadBlogPost() {
    let { slug } = useParams()
        // ...


    return (
        <div>{slug} 
        </div>
    )
};

export default ReadBlogPost;

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

Я попытался использовать слаг в качестве do c .id, чтобы получить документ публикации следующим образом:

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



import Firebase from "../../../firebase";
import BlogList from './View';


function ReadBlogPost() {
    let { slug } = useParams()
        // ...
    useEffect(() => {
        const blog = 
    Firebase.firestore.collection("blog").doc(slug);

            blog.get().then(function(doc) {
                if (doc.exists) {
                    console.log("Document data:", doc.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>{blog.title} 
            </div>
        )
    };

    export default ReadBlogPost;

Возвращает ошибку о том, что блог не определен. Я также пытался вернуть {do c .title}, но я получаю ту же ошибку. Я могу видеть все данные в консоли.

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

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

Моя следующая попытка - попытаться последовать примеру в этом учебнике .

function ReadBlogPost(blog) {
    let { slug } = useParams()
        // ...
    useEffect(() => {
        const blog = 
Firebase.firestore.collection("blog").doc(slug);

        blog.get().then(function(doc) {
            if (doc.exists) {
                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);
        });

    },
    [blog]
);


    return (
        <div><Title level={4} > {blog.title}

        </Title>

        <p>{console.log(blog)}</p>


        </div>
    )
};

export default ReadBlogPost;

Когда я пытаюсь это сделать, единственное, что странно, это то, что console.log внутри метода useEffect точно выдает все данные, но когда я регистрирую их в методе return, я получаю загрузку gibberi sh (показано на рисунке ниже). enter image description here

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

Я нашел этот учебник , который использует базу данных реального времени вместо firestore, но я попытался скопировать логи c.

Моя страница прочитанного поста теперь имеет:

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

import Firebase from "../../../firebase";
import BlogList from './View';
import { Card, Divider, Form, Icon, Input, Switch, Layout, Tabs, Typography, Tag, Button } from 'antd';
const { Paragraph, Text, Title } = Typography;


 const ReadBlogPost = () => {
    const [loading, setLoading] = useState(true);
    const [currentPost, setCurrentPost] = useState();



    let { slug } = useParams()

    if (loading && !currentPost) {
        Firebase
          .firestore
          .collection("blog")
          .doc(slug)
          .get()
          .then(function(doc) {
            if (doc.exists) {
                setCurrentPost(...doc.data());
                console.log("Document data:", doc.data());
            }
          }),  

          setLoading(false)
          }

          if (loading) {
            return <h1>Loading...</h1>;
          }





    return (
        <div><Title level={4} > 
        {currentPost.caption}
        {console.log({currentPost})}

        </Title>




        </div>
    )

};
export default ReadBlogPost;

Возможно, это сообщение в блоге старое, или, может быть, это связано с использованием. js где у меня есть .jsx - что я думаю означает, что я не могу использовать , если заявления , но я не могу заставить это работать тоже. Ошибка говорит:

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

Указывает на строку, начинающуюся с Firebase.

Я избавился от всех битов загрузки, чтобы попытаться визуализировать данные. Это избавляет от вышеуказанного сообщения об ошибке на данный момент. Однако я все еще не могу вернуть значения из currentPost.

Мне действительно странно, что внутри оператора return я не могу вывести {currentPost.title} - я получаю сообщение об ошибке, в котором title не определена, но когда Я пытаюсь вывести {currentPost}, сообщение об ошибке гласит:

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

Это не имеет смысла! Мне бы очень хотелось понять, почему я могу записывать эти значения перед оператором return, а внутри оператора return я могу записать их в объект, но не могу найти способ их регистрации в качестве атрибутов.

Ответы [ 2 ]

0 голосов
/ 12 апреля 2020

Я нашел ответ, который работает для каждого атрибута, кроме отметки времени.

const [currentPost, setCurrentPost] = useState([]);

В инициализированном состоянии useState () есть пустой массив.

По отношению к отметкам времени - Я столько раз проходил через этот ад с временными метками пожарного магазина - совсем недавно здесь . Решение, которое работало в декабре 2019 года, больше не работает. Вернемся к тому, чтобы рвать на себе волосы ...

0 голосов
/ 11 апреля 2020

Прежде всего: ваш useBlog() хук возвращает ожидаемые данные? Если это так, все, что вам нужно сделать, это правильно определить ваши <Link/> компоненты.

<Link 
  // This will look like /readblog/3. Curly braces mean
  // that this prop contains javascript that needs to be
  // evaluated, thus allowing you to create dynamic urls.
  to={`/readblog/${blog.id}`}
  // Make sure to open in a new window
  target="_blank"
>
  Read
</Link>

Редактировать: если вы хотите передать данные в новый компонент, вам нужно настроить хранилище, чтобы избежать выборка одного и того же ресурса дважды (один раз при монтировании списка и один раз при монтировании самого BlogPost)

// Define a context
const BlogListContext = React.createContext()

// In a top level component (eg. App.js) define a provider
const App = () => {
  const [blogList, setBlogList] = useState([])

  return (
    <BlogListContext.Provider value={{blogList, setBlogList}}>
      <SomeOtherComponent/>
    </BlogListContext.Provider>
  )
}

// In your BlogList component
const BlogList = ({ editBlog }) => {
  const { setBlogList } = useContext(BlogListContext)
  const listBlog = useBlogs()

  // Update the blog list from the context each time the
  // listBlog changes
  useEffect(() => {
    setBlogList(listBlog)
  }, [listBlog])
  return (
    // your components and links here
  )
}

// In your ReadBlog component
const ReadBlogComponent = ({ match }) => {
  const { blogList } = useContext(BlogListContext)
  // Find the blog by the id from params.
  const blog = blogList.find(blog => blog.id === match.params.id) || {}

  return (
    // Your JSX
  )
}

Есть и другие варианты для передачи данных:

  1. Через параметры URL (не рекомендуется).
  2. Просто передайте идентификатор и позвольте компоненту извлекать свои собственные данные при монтировании.
...