网格 /文档数组未加载时首次单击

发布于 2025-02-03 18:48:32 字数 2733 浏览 2 评论 0原文

我试图将一系列文档加载到Firebase Firestore的网格(react.js)中,但并未在“导航”按钮的第一个点击中显示。 即使我添加了一个加载组件,也可以在网格之前显示 - 它仍然不起作用

getAuthor func

const getAuthor = async (uid) => {
    const author = await getDoc(doc(getFirestore(app), 'StripeCustomers', uid));
    if (author.exists()) {
        return author.data();
    }
    return null;
}

getGrid func

const getGrid = async (type) => {
    let gridData = [];
    const grid = await getDocs(collection(getFirestore(app), type));
    grid?.docs.map(item => {
        getAuthor(item.data().Author.id).then(author => {

            gridData.push({
                title: item.data().title,
                link: "/materials/type=" + type + "/uuid=" + item.id,
                thumbnail: "#",
                type: type,
                authors: [{
                    name: author.FirstName + " " + author.LastName,
                    imageUrl: author.profileUrl,
                    profileUrl: "/user/id=" + author.id
                }]

            });
        });
    });
    return gridData;
}

partial:

const Material = ({ info }) => {
    return (
        <Link to={info.link} className="flex flex-col dark:black hover:border hover:bg-gray-100 dark:hover:bg-slate-900 hover:border-gray-200 dark:hover:border-slate-800 rounded-2xl cursor-pointer overflow-hidden box-border">
            <img src={info.thumbnail} className="thumbnail aspect-video rounded-2xl" />
            <div className="flex items-center p-3 space-x-4">
                {/* <Link to='#'><img src={info.authors[0].imageUrl} className="w-12 block aspect-square rounded-full" /></Link> */}
                <div className="flex flex-col">
                    <h3 className="text-xl font-bold">{info.title}</h3>
                    {info.authors.map((author, index) => (<p key={index} className="text-sm text-gray-500">{author.name}</p>))}
                </div>
            </div>
        </Link>
    );
}

main:

const Materials = ({ groupBy }) => {
    const [grid, setGrid] = useState([]);
    
    useEffect(() => {
        getGrid(groupBy).then(gridn => {
            setGrid(gridn);
        });
    }, []);

    return (
        <div className="w-full flex flex-col justify-content items-center m-auto">
            <div className="materials w-11/12 lg:p-5 pt-5 grid 2xl:grid-cols-4 xl:grid-cols-3 lg:grid-cols-2 gap-4 gap-y-6">
                {grid && grid?.map((i) => (<Material key={i} info={i} />))}
            </div>
        </div>
    )
}

I am trying to load an array of documents into a grid (in React.js) from Firebase FireStore, but it isn't displaying on the first tap of the navigation button.
Even if I add a loading component, that displays before the grid - it still doesn't work

getAuthor func

const getAuthor = async (uid) => {
    const author = await getDoc(doc(getFirestore(app), 'StripeCustomers', uid));
    if (author.exists()) {
        return author.data();
    }
    return null;
}

getGrid func

const getGrid = async (type) => {
    let gridData = [];
    const grid = await getDocs(collection(getFirestore(app), type));
    grid?.docs.map(item => {
        getAuthor(item.data().Author.id).then(author => {

            gridData.push({
                title: item.data().title,
                link: "/materials/type=" + type + "/uuid=" + item.id,
                thumbnail: "#",
                type: type,
                authors: [{
                    name: author.FirstName + " " + author.LastName,
                    imageUrl: author.profileUrl,
                    profileUrl: "/user/id=" + author.id
                }]

            });
        });
    });
    return gridData;
}

Partial:

const Material = ({ info }) => {
    return (
        <Link to={info.link} className="flex flex-col dark:black hover:border hover:bg-gray-100 dark:hover:bg-slate-900 hover:border-gray-200 dark:hover:border-slate-800 rounded-2xl cursor-pointer overflow-hidden box-border">
            <img src={info.thumbnail} className="thumbnail aspect-video rounded-2xl" />
            <div className="flex items-center p-3 space-x-4">
                {/* <Link to='#'><img src={info.authors[0].imageUrl} className="w-12 block aspect-square rounded-full" /></Link> */}
                <div className="flex flex-col">
                    <h3 className="text-xl font-bold">{info.title}</h3>
                    {info.authors.map((author, index) => (<p key={index} className="text-sm text-gray-500">{author.name}</p>))}
                </div>
            </div>
        </Link>
    );
}

Main:

const Materials = ({ groupBy }) => {
    const [grid, setGrid] = useState([]);
    
    useEffect(() => {
        getGrid(groupBy).then(gridn => {
            setGrid(gridn);
        });
    }, []);

    return (
        <div className="w-full flex flex-col justify-content items-center m-auto">
            <div className="materials w-11/12 lg:p-5 pt-5 grid 2xl:grid-cols-4 xl:grid-cols-3 lg:grid-cols-2 gap-4 gap-y-6">
                {grid && grid?.map((i) => (<Material key={i} info={i} />))}
            </div>
        </div>
    )
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无言温柔 2025-02-10 18:48:32

如果您在调试器中检查(或添加一些记录),您会看到返回GridData在您的任何griddata.push({...})之前运行之前运行发生了,您无法返回尚未加载的东西。

一个简单的解决方案是使用Promise.All,例如:

const getGrid = async (type) => {
  const grid = await getDocs(collection(getFirestore(app), type));
  const promises = grid?.docs.map(item => getAuthor(item.data().Author.id));
  const authors = await Promise.all(promises);
  const girdData = authors.map(author => {
    return {
        title: item.data().title,
        link: "/materials/type=" + type + "/uuid=" + item.id,
        thumbnail: "#",
        type: type,
        authors: [{
          name: author.FirstName + " " + author.LastName,
          imageUrl: author.profileUrl,
          profileUrl: "/user/id=" + author.id
        }]
    }
  });
  return gridData;
}

If you check in a debugger (or add some logging), you'll see that return gridData runs before any of your gridData.push({ ... }) calls happen, and you can't return something that hasn't loaded yet.

A simple solution is to use Promise.all, like this:

const getGrid = async (type) => {
  const grid = await getDocs(collection(getFirestore(app), type));
  const promises = grid?.docs.map(item => getAuthor(item.data().Author.id));
  const authors = await Promise.all(promises);
  const girdData = authors.map(author => {
    return {
        title: item.data().title,
        link: "/materials/type=" + type + "/uuid=" + item.id,
        thumbnail: "#",
        type: type,
        authors: [{
          name: author.FirstName + " " + author.LastName,
          imageUrl: author.profileUrl,
          profileUrl: "/user/id=" + author.id
        }]
    }
  });
  return gridData;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文