0

In this talk https://reactjs.org/docs/hooks-intro.html the speaker write codes that resemble this :

class SomeComponent extends React.Component {
     constructor(props){
         super(props)
         this.handleResize.bind(this)
     }

     handleResize(){
          //do something with window.innerWidth
     }

     componentDidMount(){
         window.addEventListener('resize',this.handleResize)
     }
}

Why is the window.addEventListener part in componentDidMount ? Does it have to be ?

From the tone of the talk, I felt that this situation was pretty common.

I'm fairly new to react, and I would have put the browser api event subscription in the constructor just as well.

Is there any advantage that would have elude be as to why put this window.addEventListener in componentDidMount ? Or is it juste for readability purposes ?

redpanda
  • 91
  • 6

4 Answers4

1

In general, constructors must not have any side effects.

And also React documentation already mentioned this:

Avoid introducing any side-effects or subscriptions in the constructor. For those use cases, use componentDidMount() instead.

Fcmam5
  • 4,888
  • 1
  • 16
  • 33
  • That would mean that this is more of a convention for readability and thus maintenance than an architectural or performance issue ? – redpanda Jan 10 '20 at 15:09
  • Yes, it’s a convention for a reason :) it makes testing easier, and it prevents having some weird results for other use-cases (maybe it’s hard to reproduce them in this simple example). Also, lifecycle methods are here for a reason, we only want our code to execute when our component is mounted or before it does, not when it’s created in memory. – Fcmam5 Jan 10 '20 at 15:31
1

To me it's quite simple.

First, you only want api call or event listeners to be called/initialised only once, componentDidMount() and constructor is guaranteed to run only once per mounted component.

However, I won't put api in constructor because if you want a UI update after your data is returned from the api, you need a state change, while you cannot set state in constructor. The only place that only run once and allow you to setState is componentDidMount().

For Event listeners I think it can be put in constructor/componentDidMount. However, the official docs do recommend that to be put in componentDidMount(). Have a look at this.

componentDidMount is called after the component is mounted and has a DOM representation. This is often a place where you would attach generic DOM events.

Andus
  • 1,713
  • 13
  • 30
0

There are multiple reasons about componentDidMount()

In practice, componentDidMount is the best place to put calls to fetch data, for multiple reasons.

1- If you want to subscribe and unsubscribe your function then you need to call that function in componentDidMount() and to unsubscribe(after all operation) call in componentWillUnmount()

2-Using didMount makes it clear that data won’t be loaded until after the initial render. This reminds you to set up initial state properly, so you don’t end up with undefined state that causes errors.

3-componentDidMount() lifecycle method is called after render() to make sure successful DOM loading.

window.addEventListener('resize',this.handleResize)=> You can call in constructor as well but later if you need to unsubscribe, can't do because it's initial phase(called initially only).

akhtarvahid
  • 9,445
  • 2
  • 26
  • 29
0

The window.addEventListener define in the componentDidMount life cycle, because code defined inside componentDidMount is executed after the DOM have been rendered. And that would be the right moment to try to attach any event handler to element which is part of the DOM.

But if you did so inside constructor, there are many chance for that to be called before the DOM had been rendered completely.

Read more here

Yves Kipondo
  • 5,289
  • 1
  • 18
  • 31
  • 1
    For me, as the initial non-react generated dom is rendered by the browser before the first React component is rendered, the window global variable is already available for the first react component constructor. What am I missing ? – redpanda Jan 10 '20 at 15:08