NodeJS 无法将从后端返回的MongoDB文档数组Map到React组件

qzlgjiam  于 2023-01-30  发布在  Node.js
关注(0)|答案(1)|浏览(101)

我正在尝试让我的前端调用后端来获取存储在MongoDB数据库中的所有“blog post”,目前只有一个文档需要测试。
在后端,我有这个API端点:

app.get("/api/blogs", async (req, res) => {
    console.log("Getting blog items...");
    try{
        const blogs = await blogActions.getBlogItems();
        res.status(200).json({blogs});
    } catch (err) {
        console.log(err)
    }
});

这将使用此函数调用一个单独的JS文件:

const { MongoClient } = require('mongodb');
const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri);

const connection = async () => {
    try {
        const database = client.db('personalwebsite');
        const blogs = database.collection('blogs');

        return blogs;
    } catch (err) {
        console.log(err);
    }
}

const getBlogItems = async () => {
    const conn = await connection();
    try {
        return await conn.find({}).toArray();
    } catch (err) {
        console.log(err);
    }
};

然后,在我的React前端中,我尝试获取返回的数组并将其设置为Array,以便Map到它,并为从数据库返回的每个博客创建一个新的BlogItem组件:

import { useState, useEffect } from "react";
import Navbar from "../components/Navbar.tsx";
import BlogItem from "../components/BlogItem.tsx";
import '../styles/Blog.css';

export default function Blog () {
    const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false);
    const [isAdmin, setIsAdmin] = useState<boolean>(false);
    const [token, setToken] = useState<string>('');
    const [blogs, setBlogs] = useState([]);

    useEffect(() => {
        setToken(localStorage.getItem('token'));

        async function checkToken () {
            const response = await fetch('/api/token', {
              method: 'POST',
              headers: {
                  'Content-type': 'application/json',
                  'Authorization': `Bearer ${token}`
              }
            });
            if (response.ok){
              const jsonResponse = await response.json();
              if (jsonResponse.delete){
                localStorage.clear();
                return false;
              }
              return true;
            } else {
              console.log("Failed to fetch status of the User Login Session.");
            }
        }

        async function checkIfAdmin () {
            const response = await fetch('/api/users/permissions', {
                method: 'POST',
                headers: {
                    'Content-type': 'application/json',
                    'Authorization': `Bearer ${token}`
                }
            });
            if(response.ok) {
                const jsonResponse = await response.json();
                if (jsonResponse.role === 'admin') {
                    setIsAdmin(true);
                } else {
                    setIsAdmin(false);
                }
            }
        }

        async function getBlogItems () {
            try {
                const response = await fetch('/api/blogs');
                const data = await response.json();
                console.log("Before setBlogs", data.blogs)
                if(data.blogs.length > 0) {
                    setBlogs(data.blogs);
                }
            } catch (err) {
                console.log(err);
            }
        }
    
        if (token) {
            checkToken().then(isValid => {
                if (!isValid) return;
                checkIfAdmin();
            });
        }
        
        getBlogItems();

    }, [])

    console.log("After setBlogs", blogs);

    return (
        <div className="App">
          <Navbar />
          <main className="main-content">
            <div className="blogs-container">
                {blogs.length > 0 ? (
                    blogs.map((blog) => (
                        <BlogItem
                            key={blog._id}
                            title={blog.title}
                            shortDesc={blog.shortDesc}
                            imgSrc={blog.imgSrc}
                            pubDate={blog.pubDate}
                        />
                    ))
                ) : (
                    <div>Loading...</div>
                )}  
            </div>
            <div className="most-popular"></div>
          </main>
        </div>
    );
}

我已经尝试了很多不同的方法来尝试让它正确工作。起初我认为这只是一个数据返回不够快的问题,但即使在让代码等待数据返回并设置数组之后。我得到一个错误,即对象作为React子对象无效。
这意味着是一个对象数组,这样我就可以访问组件中元素的每个对象的属性,但我无法让它在我的生命中工作。我花了一段时间使用ChatGPT尝试取得一些进展,但这似乎是一个需要人为干预的问题。

vh0rcniy

vh0rcniy1#

所以这很烦人,但问题不在于我的代码的其余部分,而实际上是BlogItem组件的props只封装在括号中。
以下是组件:

export default function BlogItem ({title, shortDesc, imgSrc, pubDate}) {
    return (
    <div className="blog-item">
        <img src={imgSrc} className="blog-image" />
        <h1 className="blog-title">{title === "" ? "Placeholder Title" : title }</h1>
        <p className="blog-short-desc">{shortDesc}</p>
        <p className="blog-date">{pubDate}</p>
    </div>
    );
}

修复了标题shortDesc、imgSrc、pubDate。所有这些都需要用大括号括起来。现在可以正常工作了:\

相关问题