question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

version 3 loses component local state

See original GitHub issue

I have an accordion that has local state that tracks which panes are open. When I update one of the panes, the open panes collapse because (I’m assuming) the accordion’s state is being set back the default state.

There are many moving pieces so I’m not sure what to point out. I’m using webpack-dev-middleware, webpack-hot-middleware, and my config looks like this:

const config = Object.assign({}, projectConfig, {
  entry: [
    "webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&quiet=true",
    "react-hot-loader/patch",
    path.join(__dirname, "../public/js/main.js")
  ]
});

config.plugins = config.plugins.concat([
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NoErrorsPlugin()
]);

config.module.loaders = config.module.loaders.concat([
  { test: /\.js$/,
    exclude: /(node_modules|bower_components)/,
    loader: "react-hot-loader/webpack" }
]);

// ...

app.use(webpackDevMiddleware(compiler, {
  publicPath: config.output.publicPath,
  noInfo: true,
  stats: {
    colors: true
  }
}));

app.use(webpackHotMiddleware(compiler, {
  log: console.log,
  path: '/__webpack_hmr',
  heartbeat: 10 * 1000
}));

My component files are definitely being transformed, here is a snippet:

// ...
module.exports = connect(
      (state, props) => ({
        breakpoints: _getBreakpoints(state)
      }),
      dispatch => bindActionCreators(actions, dispatch)
    )(Breakpoints);


     ;(function () { /* react-hot-loader/webpack */ if (process.env.NODE_ENV !== 'production') { if (typeof __REACT_HOT_LOADER__ === 'undefined') { return; } if (typeof module.exports === 'function') { __REACT_HOT_LOADER__.register(module.exports, 'module.exports', "Breakpoints.js"); return; } for (var key in module.exports) { if (!Object.prototype.hasOwnProperty.call(module.exports, key)) { continue; } var namedExport = void 0; try { namedExport = module.exports[key]; } catch (err) { continue; } __REACT_HOT_LOADER__.register(namedExport, key, "Breakpoints.js"); } } })();
    /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(17)))

Finally, how I render the root component:

function renderToolbox() {
  ReactDOM.render(
    React.createElement(
      AppContainer,
      null,
      React.createElement(
        Provider,
        { store },
        React.createElement(require("./components/TabList"))
      )
    ),
    document.querySelector("#mount")
  );
}

if(module.hot) {
  module.hot.accept('./components/TabList.js', () => {
    renderToolbox();
  });
}

Looking at AppContainer, I don’t see where it would save local state. I’m requiring the new version of TabList which ends up requiring the new version of my component, and it appears to just be re-rendering my whole app with the new component, and I don’t see where state is transferred across these instances.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:23 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
pocketjosocommented, Aug 30, 2017

TLDR: don’t use withRouter for the exported component used as as top level route component with react-router (and the Router)

Just wanted to report what was the problem in my case causing local state to be lost with RHL3: The top level component we passed to our react-router Router component (same problem with react-router 3 and 4) was an App component that itself was exported via a withRouter(App) HOC (withRouter from react-router). I eventually discovered that this caused the App component to get re-mounted on every HMR cycle (save), causing the local state everywhere to be lost.

Solution for us: Move the withRouter wrapping to sub components; don’t use it with the top level component put inside the Router. Now HMR works and local state is kept.

Note for point of interest: we were, and still are, wrapping our App export in an connect - this does not cause any problem. Not sure exactly what withRouter does that causes this problem.

0reactions
PeterKottascommented, Nov 8, 2017

Cool, that makes perfect sense. But it’s still quite a problem for me 😦 Not exactly sure how to approach it as: a) I am using swesome-typescript-loader so can’t use that babel plugin b) I have so many of these I’ll tear half of my hair out before I’d manage to do it all manually.

was this always a no no with hmr? I could have sworn this was working at some point in time. Maybe the principles of that plugin could be used to build a lib that could deconstruct these in a fashion that wouldn’t force one to use babel. I’d have to think about it a bit.

For dev experience, I guess I could fake the initial state to “working state” to allow me to work with HMR, it’s a bit of a pain though

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to keep React component state between mount/unmount?
1) The most obvious place to save the state is within the parent component. · 2) You can save the state elsewhere, like...
Read more >
Preserving and Resetting State - React Docs
When you give a component state, you might think the state “lives” inside the component. But the state is actually held inside React....
Read more >
Managing Component State with the useState Hook - Manning
Some state is shared across the application, some by a few components and some is managed locally by a component itself. If components...
Read more >
5 Methods to Persisting State Between Page Reloads in React
One of the straightforward options is to use localStorage in the browser to persist the state. Let's take a look at an example....
Read more >
<Provider> misses state changes that occur between when its ...
Connected components should always see the most recent Redux state, even if that state changed between when <Provider> was constructed and when ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found