Home > database >  My React component is re-rendering, cannot figure out why
My React component is re-rendering, cannot figure out why

Time:04-22

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.

CodePudding user response:

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

  1. Attach listener
  2. Fire listener method straight away
  3. setMessages is called
  4. Because setMessages is being called, the component performs another render, which results in
  5. A listener being attached again
  6. The listener method being fired straight away
  7. setMessages 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
}
  • Related