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()
}, [])
CodePudding user response:
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.
CodePudding user response:
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>)}
)
}
CodePudding user response:
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>
);