erikras / react-redux-universal-hot-example

A starter boilerplate for a universal webapp using express, react, redux, webpack, and react-transform
MIT License
11.99k stars 2.5k forks source link

componentDidMount called twice for initial load #429

Closed snackycracky closed 9 years ago

snackycracky commented 9 years ago

Hey,

the method componentDidMount is called twice on the client, when initially accessing any route e.g. localhost:3000/login (I see this in the browser console logs when adding something like console.log('componentDidMount called'))

When one clicks on other links in the menu bar after the initial load then the lifecycle function will not be called twice for other containers. It's only for the first access (first container/component beeing loded).

For me it's problematic at the moment because the Rx.Observable subscription and the socket.io event listener is defined at the main-app-page.

So as a workaround for continuing developing I always access a different page and from there I go to the main-app-page to have componentDidMount beeing called only once.

Maybe this has to do something with the server-side-rendering but I don't see the point that in the browser it's called twice.

erikras commented 9 years ago

How was this resolved? Was it developer error? Happens a lot in my projects. :-)

snackycracky commented 9 years ago

No it's not resolved, I thought like nobody cared or it's not a problem for anyone.

For my case it's not really a huge issue anymore because now I implement the lifecycle method componentWillUnmount() to call .dispose() on my Rx.Observable subscription and removeAllListeners for the socket.io stream.

But still IMO the "unnecessary behavior" persists.

erikras commented 9 years ago

Leave the ticket open. Sometimes stale ones get solved. I don't have any experience with Rx.Observable, so I can't really be of much help, but there are helpful people around.

snackycracky commented 9 years ago

I think this issue is related to react-router or to the isomorphic rendering.

snackycracky commented 9 years ago

I would first start to investigate by turning off server side rendering and see if componentDidMount is still called twice in the browser. Is there a super easy way to temporarily disable server side rendering?

stevoland commented 9 years ago

It's just because we do 2 initial renders in dev mode to avoid getting warnings about mismatched client/server markup when we introduce the devtools. Doesn't affect production.

erikras commented 9 years ago

I think @stevoland nailed it. If you disable devtools (see bottom of readme for how), it should go away.

lochstar commented 9 years ago

Great, I was wondering why this happens. Makes sense.

quicksnap commented 9 years ago

@snackycracky Does disabling devtools fix it for you? If so, praise be @stevoland and let's close this sucker!

snackycracky commented 9 years ago

yes it solves the issue, but I tend to prefer to have those warnings instead of a double load. @stevoland how can I disable the 2 initial renders without disabling the devtools?

stevoland commented 9 years ago

Just put a condition around the first render, something like https://github.com/erikras/react-redux-universal-hot-example/pull/279/files

snackycracky commented 9 years ago

:+1:

clkao commented 8 years ago

It seems this issue still exists as #279 was reverted by #280

happypoulp commented 8 years ago

Another approach to render devTools without using 2 initial renders could be to render server-side without devTools and to inject devTools on componentDidMount (only executed client-side).

Ex:

import React, { Component } from 'react'
import { connect } from 'react-redux'

@connect((state) => {
  return {
    render_dev_tools: state.render_dev_tools
  }
})
export default class App extends Component {

  componentDidMount() {
    if (__DEVTOOLS__) {
      this.props.dispatch({ type: 'RENDER_DEV_TOOLS' })
    }
  }

  render() {
    let devTools = null
    if (__DEVTOOLS__ && this.props.render_dev_tools) {
      const DevTools = require('redux/devtools')
      devTools = <DevTools/>
    }

    return (
      <div id="app">
        {/* ... */}
        { devTools }
      </div>
    )
  }
}
zhiyelee commented 8 years ago

+1 for bug stills here in dev mode

jessedobbelaere commented 8 years ago

+1 for this bug that keeps bothering me. I tried to put a condition around the server-side render, or use the inject method described above, but I keep getting things like:

Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
 (client) ctid=".g2zjxb5mgw"><div data-reactid=".g
 (server) ctid=".g2zjxb5mgw"><noscript data-reacti
gmcnaughton commented 8 years ago

+1 I was going through the React tutorial and was confused why my componentDidMount kept getting called twice.

Setting window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {} suppresses the console warning, but doesn't stop componentDidMount from getting called twice (because of #280)

notno commented 8 years ago

+1 Still seems to be an issue. componentDidMount is still getting called twice.

sarjford commented 8 years ago

I've tried running my app in production mode and it's still double rendering. If anyone has any other fixes I could try, I'd appreciate it. I've been researching this issue and it seems to be a common problem with react router. Also I couldn't find how to disable devtools in the readme as @erikras mentioned. I'm new to this, though, so might have not understood what to look for. If anyone could point me in that direction, it would be helpful.

headwinds commented 8 years ago

@sarjford look in src > webpack and open the dev.config.js

At the bottom you'll find: plugins: [ // hot reload new webpack.HotModuleReplacementPlugin(), new webpack.IgnorePlugin(/webpack-stats\.json$/), new webpack.DefinePlugin({ __CLIENT__: true, __SERVER__: false, __DEVELOPMENT__: true, __DEVTOOLS__: false // <-------- DISABLE redux-devtools HERE }),

when you set DEVTOOLS to false, voila! no more devtools and double rendering will go away

lyhoanglong commented 7 years ago

I got error too, componentDidMount is still getting called twice. anyone have a solution?

gaving commented 7 years ago

@lyhoanglong Abandon all hope on this ancient, unmaintained boilerplate and have a look at https://github.com/facebookincubator/create-react-app before you squander anymore time!

jarecsni commented 7 years ago

Still happening, why is this closed? The didMount is called 2x and maybe that's why always 2 debugger windows are spawned. Can we please reopen this? (This is happening on an app I've created with the new recommended create-react-native-app (expo).

jarecsni commented 7 years ago

hm, maybe we need to raise a new one against react-native...

proton1k commented 7 years ago

@sarjford did you find out the reason ?

ngyangjo commented 6 years ago

@gaving What are you referring to? I'm using create-react-app but still getting this.

ngyangjo commented 6 years ago

Nevermind. Turns out I was passing same component two two other component. That was causing the component to render in two places, hence causing componentDidMount() to get called twice.

01000101 commented 4 years ago

My issue was resolved after I removed a duplicate Route.

          <Route path="/thing/stuff" component={ThingStuff}/>
          <Route path='/thing/stuff/:foo' component={ThingStuff} />
CaliforniaMountainSnake commented 2 years ago

I still continue to face this issue in development mode in 2022... First picture - development mode, second one - production mode.

package.json:

    "dependencies": {
        "core-js": "^3.21.1",
        "prop-types": "^15.8.1",
        "react": "^18.0.0",
        "react-dom": "^18.0.0"
    },

Screenshot_20220417_203655 Screenshot_20220417_203626

artbindu commented 4 months ago

Still facing the issue in developer mode If I remove the React.StrictMode then issue is resolved image