I'm building a React App with Firebase and my component is constantly re-rendering.
I tried some things that didn't work (because they couldn't work, like settig useState inside the callback).
This is the code, please help!
const [user, setUser] = useState(null);
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const msgRef = ref(db, 'messages');
onValue(msgRef, snapshot => {
const msg = snapshot.val();
if (Object.values(msg) != messages) {
setMessages(Object.values(msg));
}
})
Also, I know it is re-rendering because of this code beacuse I console.logged it.
If your read the firebase documentation, you see the following
This method is triggered once when the listener is attached and again every time the data, including children, changes
When your component renders the following is happening
setMessages
is calledsetMessages
is being called, the component performs another render, which results insetMessages
is called... And so on
The body of a functional component should not contain side effects (that is code that does something other than produce the render output). To trigger a side effect when a component first renders, you need to use a useEffect hook. It's going to look something like this:
const Component = () => {
const [messages, setMessages] = useState([]);
useEffect(() => {
const unsubscribe = onValue(msgRef, snapshot => {
const msgRef = ref(db, 'messages');
const msg = snapshot.val();
if (Object.values(msg) != messages) {
setMessages(Object.values(msg));
}
})
// A function that is returned from the useEffect callback
// will be called when the component unmounts.
// This is the correct way to remove the listener
// when you don't need it any more
return unsubscribe
// The empty array passed into the second argument will result in
// this function *only ever being called once*
}, [])
// rest of component code
}