如何设置函数在另一个函数之后渲染?

时间:2021-03-21 23:09:16

标签: reactjs firebase asynchronous

我将我的 react 应用程序连接到了 firebase,我认为问题是页面在从我的数据库中获取数据之前加载,我可以做些什么来延迟函数直到它完成获取数据之后?

function getPosts(){
    db.collection("Posts").get().then(snapshot =>{
        snapshot.docs.forEach(docs =>{
             createPost(
                 docs.data().postName,
                 docs.data().createdAt,
                 docs.data().postContent,
             )
        })
    })
}

getPosts();

function Blog(){
    return (
    <div>
              <Navbar/>
<div className="container">
<div className="row" id="posts-collection">

</div>
</div>
</div>
    )
}

export default Blog;

2 个答案:

答案 0 :(得分:1)

正如 MehmetDemiray 已经展示的那样,您可以在函数组件中加载数据作为效果,但该答案假设您只想跟踪加载状态。

如果你想使用加载的数据来显示post数据,那么你还需要存储返回的数据。

const Blog: React.FunctionComponent = () => {
    // state to store data returned by async call. (originally set to null).
    const [posts, setPosts] = React.useState(null);

    // use an effect to load async data.
    // the effect only runs on component load and every time the data in
    // the dependency array changes "[setPosts]" (reference comparison).
    React.useEffect(() => {
        // Create funtion to run async logic to load posts.
        const getPosts = () => {
            // load posts
            db.collection("Posts").get().then(snapshot => {
                // map loaded posts to an array of easy to manage objects.
                const loadedPosts = snapshot.docs.map(docs => {
                    return {
                        name: docs.data().postName,
                        createdAt: docs.data().createdAt,
                        content: docs.data().postContent,
                    }
                });

                // store loaded posts in state.
                setPosts(loadedPosts ?? []);
            });
        };

        // run async function created above.
        getPosts();
    }, [setPosts])

    // posts will remain null until the async function has loaded data.
    // you can manually track loading in a separate state if required.
    if (posts === null) {
        // Show loading view while loading.
        return (
            <div>
                Loading Posts...
            </div>
        );
    }

    // map out posts view after posts have been loaded.
    return (
        <div>
            {posts.map(post => (
                <div>
                    <div>{post.postName}</div>
                    <div>{post.createdAt}</div>
                    <div>{post.content}</div>
                </div>
            ))}
        </div>
    );
};

答案 1 :(得分:0)

渲染jsx之前需要加载控件。看起来像这样;

import {useEffect, useState} from 'react';

function Blog(){
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setLoading(true);
    function getPosts(){
      db.collection("Posts").get().then(snapshot =>{
        snapshot.docs.forEach(docs =>{
          createPost(
            docs.data().postName,
            docs.data().createdAt,
            docs.data().postContent,
          )
        })
      setLoading(false);
      })
    }
    getPosts();
  }, [])

  return (
  loading ? 
  <div>
  < Navbar/>
    <div className="container">
      <div className="row" id="posts-collection">

      </div>
    </div>
  </div> : null
  )
}

export default Blog;