There are a couple of things there. First, to fix the code, you could update your useEffect to this:

useEffect(() => {
    messagesRef.on('child added', snapshot => {
    const message = snapshot.val();
    message.key = snapshot.key;

    setMessages(messages.concat(message)); // See Note 1
}, []); // See Note 2

Note 1

The setMessages line is how you update your state. useState is a little bit different from the "old" setState in a sense that will completely replace the state value. React documentation says:

This is because when we update a state variable, we replace its value. This is different from this.setState in a class, which merges the updated fields into the object.

Note 2

React Hooks changes the way we build apps and it is not a real "translation" from the old lifecycles.

The empty brackets ([]) in the last line, will make your code "similar" to componentDidMount, but most importantly, will make your effect run only once.

Dan Abramov said (removed some of the original text):

While you can useEffect(fn, []), it’s not an exact equivalent. Unlike componentDidMount, it will capture props and state. So even inside the callbacks, you’ll see the initial props and state. (...) Keep in mind that the mental model for effects is different from componentDidMount and other lifecycles, and trying to find their exact equivalents may confuse you more than help. To get productive, you need to “think in effects”, and their mental model is closer to implementing synchronization than to responding to lifecycle events.

Full article about useEffect here.

Answer from Bruno Monteiro on Stack Overflow
Top answer
1 of 3
19

There are a couple of things there. First, to fix the code, you could update your useEffect to this:

useEffect(() => {
    messagesRef.on('child added', snapshot => {
    const message = snapshot.val();
    message.key = snapshot.key;

    setMessages(messages.concat(message)); // See Note 1
}, []); // See Note 2

Note 1

The setMessages line is how you update your state. useState is a little bit different from the "old" setState in a sense that will completely replace the state value. React documentation says:

This is because when we update a state variable, we replace its value. This is different from this.setState in a class, which merges the updated fields into the object.

Note 2

React Hooks changes the way we build apps and it is not a real "translation" from the old lifecycles.

The empty brackets ([]) in the last line, will make your code "similar" to componentDidMount, but most importantly, will make your effect run only once.

Dan Abramov said (removed some of the original text):

While you can useEffect(fn, []), it’s not an exact equivalent. Unlike componentDidMount, it will capture props and state. So even inside the callbacks, you’ll see the initial props and state. (...) Keep in mind that the mental model for effects is different from componentDidMount and other lifecycles, and trying to find their exact equivalents may confuse you more than help. To get productive, you need to “think in effects”, and their mental model is closer to implementing synchronization than to responding to lifecycle events.

Full article about useEffect here.

2 of 3
1

You tried to declare the state again instead of using the state updater

useEffect(() => {
  messagesRef.on('child added', snapshot => {
    const message = snapshot.val();
    message.key = snapshot.key;
    // setMessages is the state updater for messages
    // instead of an object with messages: messagesArray
    // just save it as an array the name is already messages
    setMessages([...messages, message]);
  });
// useEffect takes an array as second argument with the dependencies
// of the effect, if one of the dependencies changes the effect will rerun
// provide an empty array if you want to run this effect only on mount
}, []);
🌐
React
legacy.reactjs.org › docs › hooks-effect.html
Using the Effect Hook – React
If you’re familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.
🌐
Reacttraining
reacttraining.com › blog › useEffect-is-not-the-new-componentDidMount
useEffect(fn, []) is not the new componentDidMount()
January 31, 2020 - With that in place, the hooks version is doing what would have been a componentDidMount and a componentDidUpdate at the same time. So you see, the very question of "Is useEffect with an empty dependency array the new version of componentDidMount?" is a flawed question to begin with componentDidMount will most often not be refactored to useEffect(fn, [])
🌐
LogRocket
blog.logrocket.com › home › using react’s useeffect hook with lifecycle methods
Using React’s useEffect Hook with lifecycle methods - LogRocket Blog
June 4, 2024 - By simply calling the useEffect Hook and passing the callback function, we preform the equivalent of the componentDidMount lifecycle method.
🌐
Plain English
plainenglish.io › home › blog › react › componentdidmount and useeffect are not the same. here's why
ComponentDidMount and useEffect Are Not The Same. Here's Why
December 1, 2012 - Methods like componentDidMount() ... of programmers assume that they can replace the behavior of componentDidMount() with useEffect(fn, [])....
🌐
DEV Community
dev.to › trentyang › replace-lifecycle-with-hooks-in-react-3d4n
React Hooks Componentdidmount: Replace lifecycle with hooks in React - DEV Community
January 6, 2019 - Unlike componentDidMount and componentDidUpdate, the function passed to useEffect fires after layout and paint, during a deferred event.
🌐
DigitalOcean
digitalocean.com › community › tutorials › react-replacing-component-lifecycles-with-useeffect
Replacing Component Lifecycles with the useEffect Hook, in React | DigitalOcean
September 9, 2020 - Let’s talk about the useEffect hook for a moment. Much like componentDidMount, useEffect will immediately call our function.
Find elsewhere
🌐
Codemzy
codemzy.com › blog › how-to-use-react-useeffect-like-componentdidmount
How to use React useEffect like componentDidMount - Codemzy's Blog
April 6, 2022 - If you truly need to replicate componentDidMount you can switch out useEffect with useLayoutEffect to run your function before rendering.
🌐
GeeksforGeeks
geeksforgeeks.org › how-to-simulate-componentdidmount-with-useeffect
How to simulate componentDidMount with useEffect? | GeeksforGeeks
April 28, 2025 - We define an effect using useEffect that fetches data from an API when the component mounts. The effect runs only once after the initial mount because we provide an empty dependency array [], simulating componentDidMount.
🌐
Codinn
codinn.dev › articles › react-componentdidmount-equivalent-useeffect-hooks-in-functional-component
Understanding the Importance of componentDidMount in Functional Component
March 19, 2023 - To use componentDidMount functionality in functional components, you can use the useEffect hook. The useEffect hook takes two arguments: a function that performs the desired effect and an array of dependencies that determine when the effect ...
Top answer
1 of 11
664

For the stable version of hooks (React Version 16.8.0+)

For componentDidMount

useEffect(() => {
  // Your code here
}, []);

For componentDidUpdate

useEffect(() => {
  // Your code here
}, [yourDependency]);

For componentWillUnmount

useEffect(() => {
  // componentWillUnmount
  return () => {
     // Your code here
  }
}, [yourDependency]);

So in this situation, you need to pass your dependency into this array. Let's assume you have a state like this

const [count, setCount] = useState(0);

And whenever count increases you want to re-render your function component. Then your useEffect should look like this

useEffect(() => {
  // <div>{count}</div>
}, [count]);

This way whenever your count updates your component will re-render. Hopefully this will help a bit.

2 of 11
53

There is no exact equivalent for componentDidMount in react hooks.


In my experience, react hooks requires a different mindset when developing it and generally speaking you should not compare it to the class methods like componentDidMount.

With that said, there are ways in which you can use hooks to produce a similar effect to componentDidMount.

Solution 1:

useEffect(() => {
  console.log("I have been mounted")
}, [])

Solution 2:

const num = 5

useEffect(() => {
  console.log("I will only run if my deps change: ", num)
}, [num])

Solution 3 (With function):

useEffect(() => {
  const someFunc = () => {
    console.log("Function being run after/on mount")
  }
  someFunc()
}, [])

Solution 4 (useCallback):

const msg = "some message"

const myFunc = useCallback(() => {
  console.log(msg)
}, [msg])

useEffect(() => {
  myFunc()
}, [myFunc])

Solution 5 (Getting creative):

export default function useDidMountHook(callback) {
  const didMount = useRef(null)

  useEffect(() => {
    if (callback && !didMount.current) {
      didMount.current = true
      callback()
    }
  })
}

It is worth noting that solution 5 should only really be used if none of the other solutions work for your use case. If you do decide you need solution 5 then I recommend using this pre-made hook use-did-mount.

Source (With more detail): Using componentDidMount in react hooks

🌐
Code Daily
codedaily.io › tutorials › Create-a-componentDidMount-useEffect-hook-in-React
Create a componentDidMount useEffect hook in React
November 19, 2018 - In this lesson we'll explore how to create `useEffect` call, and listen to the window for mouse movement. We'll learn about cleaning up our effects, and how to pass an empty array into the second argument of our effect to create a componentDidMount like effect.
🌐
Atomizedobjects
atomizedobjects.com › blog › react › using-componentdidmount-in-react-hooks
Using componentDidMount in react hooks | Atomized Objects
This is great in really simple use cases, but if you need to have any kind of external dependency in your componentDidMount function, this will not work for you because it can create stale values from previous renders and will otherwise be buggy. In the case you do have an external dependency, the next thing you should try would be to include the dependency in the dependency array of your useEffect hook so the effect only runs whenever that dependency changes like in the following example.
🌐
JavaScript in Plain English
javascript.plainenglish.io › componentdidmount-and-useeffect-are-not-the-same-heres-why-cea02f474c82
ComponentDidMount and useEffect Are Not The Same. Here’s Why | by Tino Caer | JavaScript in Plain English
August 19, 2020 - Methods like componentDidMount() ... of programmers assume that they can replace the behavior of componentDidMount() with useEffect(fn, [])....
🌐
DhiWise
dhiwise.com › blog › design-converter › useeffect-vs-componentdidmount-how-they-work-in-react
UseEffect vs. ComponentDidMount: A Clear Comparison
March 17, 2025 - By using an empty dependency array, the useEffect hook runs only once after the first render, mimicking componentDidMount.
🌐
GeeksforGeeks
geeksforgeeks.org › how-useeffect-replaces-componentdidmount-and-componentdidupdate-methods
How useEffect replaces componentDidMount and ...
February 19, 2024 - Your All-in-One Learning Portal. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.
🌐
Medium
medium.com › @elfsensoz › what-are-the-differences-between-useeffect-and-componentdidmount-8f4058d35fa9
What are the differences between useEffect and componentDidMount? | by Elif Cicek Sensoz | Medium
January 11, 2023 - In summary, useEffect is more powerful and flexible than componentDidMount, as it allows you to synchronize your component with an external system on every render, rather than just the initial render.
🌐
Medium
medium.com › @conboys111 › whats-the-modern-equivalent-of-componentdidmount-in-react-282d8bd723b8
What’s the Modern Equivalent of componentDidMount in React? | by myHotTake | Medium
December 3, 2024 - With useEffect, I can specify, “Run this setup logic just once!” by passing an empty array [] as the dependency list. It’s like telling my reminder system: "Only alert me once, no matter how much the garden changes after this." So now, I efficiently plant my seeds and set everything up, just like I would have with componentDidMount, but with a sleeker, modern approach.