I have this Post component which mounts if the user types in the Id of an existing post in firebase:
<Route path='/posts/:id' component={Post} />
However, console logging this component sends back the log indefinitely causing my browser and actions on the page to be really slow.
Heres the content of the Post component, I think it's something to do with the way I'm setting the state in useEffect but I'm not sure how to fix it. I've tried React.Memo and that didn't work:
function Post(props: RouteComponentProps<PostParams>) {
const [postData, setPostData] = useState({ title: '', body: '', author: '', time: 0, photoURL: '', likes: 0, dislikes: 0});
const [existingComments, setExistingComments] = useState([])
const [commentContent, setCommentContent] = useState('');
const isMounted = useRef(false);
const db = fb.firestore();
const ref = db.doc(`posts/${props.match.params.id}`)
useEffect(():any => {
isMounted.current = true;
ref.get().then((doc: any) => {
if(doc.exists && isMounted.current) {
setPostData(doc.data().content);
setExistingComments(doc.data().comments ? doc.data().comments : [])
}
});
return ()=> isMounted.current = false;
});
return (
//... some html that displays the information I've got from firebase
Thanks in advance for your help :)
When you're updating the state inside useEffect
, this triggers a rerender because of the state change and once the component updates, useEffect
runs again which changes the state triggering another render cycle, because of this pattern your component keeps rerendering.
You can add a dependency array to tell useEffect
to run only when the component mounts and also when something changes, like this:
function Post(props: RouteComponentProps<PostParams>) {
const [postData, setPostData] = useState({ title: '', body: '', author: '', time: 0, photoURL: '', likes: 0, dislikes: 0 });
const [existingComments, setExistingComments] = useState([])
const [commentContent, setCommentContent] = useState('');
useEffect((): any => {
const db = fb.firestore();
const ref = db.doc(`posts/${props.match.params.id}`)
ref.get().then((doc: any) => {
if (doc.exists && isMounted.current) {
setPostData(doc.data().content);
setExistingComments(doc.data().comments ? doc.data().comments : [])
}
});
return () => { };
}, [setPostData, setExistingComments]);
// setPostData, setExistingComments won't get a new reference for every render so they won't cause useEffect to run
return (<></>);
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments