Functional components force your component lifecycle into a funnel where the lifecycle becomes obvious, because all the inter-dependencies are already there.
For componentDidMount, you can replicate this easily with hooks:
const Hello = () => {
const mounted = useRef(false)
useEffect(() => {
if (!mounted.current) {
mounted.current = true
console.log("Mounted!");
}
}, [])
return <>Hello</>
}
Extracting anything into a hook is trivial: function useMounted(f) {
const mounted = useRef(false)
useEffect(() => {
if (!mounted.current) {
mounted.current = true
f()
}
}, [])
}
const Hello = () => {
useMounted(() => {
console.log("Mounted!");
})
return <>Hello</>
}
Implementing an unmount callback is also trivial.The useMounted() example, coincidentally, shows a real benefit to hooks: Easy extraction of reusable logic. Hooks are like plugins this way. For example, one hook I've written that I use all the time is this [1], it lets you get a callback every time your component resizes. If you were to do this with a class-based component, you'd have to use an ugly HOC, which results in lots of unnecessary wrapping/nesting.
For componentDidUpdate, useMemo() is arguably easier to deal with.
[1] https://gist.github.com/atombender/b95bbd2014f6a3ec303b843a9...