Why are browser api event subscribed to in componentDidMount in React?

componentdidupdate
getderivedstatefromprops
useeffect
react hooks
react lifecycle hooks
componentdidmount example
componentdidmount hooks
react state

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 ?

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.

Using the Effect Hook – React, Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples This is why in React classes, we put side effects into componentDidMount and componentDidUpdate . Inside our effect, we set the document title using the document.title browser API. Handling Events � 7. Post-mount with componentDidMount(). The last step in the Birth/Mount life cycle phase is our post-mount access via componentDidMount().This method is called once all our children Elements and our Component instances are mounted onto the Native UI.

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.

React.Component – React, This page contains a detailed API reference for the React component class definition. If you need to interact with the browser, perform your work in componentDidMount() or the other lifecycle methods Binding event handler methods to an instance. Avoid introducing any side-effects or subscriptions in the constructor. Due to the fact that JavaScript events are async, when you make an API call, the browser continues to do other work while the call is still in motion. With React, while a component is rendering it doesn’t wait for componentWillMount() to finish, so the component continues to render.

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

Patterns for data fetching in React, We explore the most common data fetching strategies in React, paired with examples and alternatives. The JSONPlaceholder API is great when you want to test some but it is still a legitimate way to get data from the server to the browser. OK, it's settled — we'll fetch our data in componentDidMount() . I am trying to fetch an api inside componentDidMount. The api result will be set to the component's state and the state mapped and passed to a children component. If I fetch the api using the fetch method inside the componentDidMount everything works fine: componentDidMount(){fetch(apiToFetch).then((result) => result.json())

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).

A beginners guide to the React component lifecycle, The componentDidMount() method � Connect a React app to external applications, such as web APIs or JavaScript frameworks. � Set Timers using� Because of the nature of async events in JavaScript, when you kick off an API call, the browser goes back to doing other work in the meantime. When React is rendering a component, it doesn’t wait for componentWillMount to finish whatever it started – React marches on and continues to render.

Declarative API for installing global DOM event handlers � Issue , addEventListener in componentDidMount but since React is listening al. Declarative API for installing global DOM event handlers #285 Your components could subscribe and unsubscribe as they see fit. my component or even outside the browser (although React's event hub would capture those by� componentDidMount is for side effects. Adding event listeners, AJAX, mutating the DOM, etc. componentWillMount is rarely useful; especially if you care about server side rendering (adding event listeners causes errors and leaks, and lots of other stuff that can go wrong).

React: Component Lifecycle Events | by Joshua Blankenship, React lets you define components as classes or functions. I also should not directly interact with the browser. render will not be invoked if This method is a good place to set up any subscriptions. Here we use componentDidMount() to connect to the YouTube API and get videos when the components� In this tutorial we are going to learn how to fetch data with the fetch api and the ComponentDidMount lifecycle method. We will also learn how to go about displaying the data after we retrieve it.

How to work with React the right way to avoid some common pitfalls, Or when you call an API and while the promise is pending, the component get To fix, cancel all subscriptions and asynchronous tasks in the the first 5 seconds as soon as the component mounts (componentDidMount). React defines these synthetic events according to the W3C spec, so you don’t need to worry about cross-browser compatibility. See the SyntheticEvent reference guide to learn more. When using React, you generally don’t need to call addEventListener to add listeners to a DOM element after it is created.

Comments
  • That would mean that this is more of a convention for readability and thus maintenance than an architectural or performance issue ?
  • 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.
  • 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 ?