我的 React 组件正在重新渲染,不知道为什么

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

我正在使用 Firebase 构建一个 React 应用程序,我的组件不断地重新渲染。
我尝试了一些不起作用的东西(因为它们不起作用,比如回调中的 settig useState)。 这是代码,请帮忙!

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));
  }
})

此外,我知道它正在重新渲染,因为我 console.logged 它是这段代码。

如果您阅读 firebase documentation,您会看到以下内容

This method is triggered once when the listener is attached and again every time the data, including children, changes

当您的组件呈现时,会发生以下情况

  1. 附加监听器
  2. 立即触发侦听器方法
  3. setMessages被称为
  4. 因为 setMessages 被调用,组件执行另一个渲染,导致
  5. 再次附加一个侦听器
  6. 立即触发侦听器方法
  7. setMessages被称为

...等等

功能组件的主体不应包含副作用(即执行某些事情的代码而不是生成渲染输出)。要在组件首次呈现时触发副作用,您需要使用 useEffect hook。它看起来像这样:

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
}