skip to Main Content

I am creating an app that is similiar in function with instagram and i have come across an issue when posting a new photo. When a user posts a new photo it is saved into this state.

const [posts, setPosts] = useState([]);

When the page renders and the useEffect runs the image is not displayed on the screen because it is async, so what i did was add "posts" as a dependencies to the useeffect. This created an infinite loop i think because it calls itself but i am unsure of any other way of going about this. This is the useEffect code.

useEffect(() => {
    const getPosts = async () => {
      const data = await getDocs(postCollectionRef);
      setPosts(data.docs.map((doc) => ({...doc.data(), id: doc.id})));
    }
    getPosts()
  }, [])

3

Answers


  1. Yes. Adding posts in the dependency array tells React to call the useEffect whenever posts state is updated. Then again, you are updating the posts state inside the useEffect. That’s what causes the infinite loop.

    I think you should just render the page after the posts are loaded.

      const [posts, setPosts] = useState([]);
      return (
        <div>
          {posts && <>{/* Render content here */}</>}
        </div>
      );
    
    Login or Signup to reply.
  2. You are correct in thinking that the useEffect is causing an infinite loop when posts is in the dependency array.
    Your useEffect dependency array does not need to contain your ‘posts’ useState because your React component will re-render itself when the state changes automatically assuming that your posts state is being used to display content.

    Login or Signup to reply.
  3. From what I can understand,

    You can wait for the API response before showing the image,
    so you could add a new loading state which will turn into false once the API request is completed.

    Check the code below

    function App() {
     const [posts, setPosts] = useState([])
     const [loading, setLoading] = useState(true)
    
     useEffect(() => {
    const getPosts = async () => {
      try {
      const data = await getDocs(postCollectionRef);
      setPosts(data.docs.map((doc) => ({...doc.data(), id: doc.id})));
       } catch {
        // handle errors
       } finally {
         setLoading(false)
       }
    }
    getPosts()
    }, []);
    
    
    return (
     {!loading && posts.map(post => <p>{post.image}</p>)}
    )
      
    

    }

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search