How can I update ONLY ONE component? Table

522 views Asked by At

I've got working application without any errors with this configs:

package.json:

 ...
    "react-hot-loader": "^3.0.0-beta.7",
    "webpack": "^3.6.0",
    "webpack-dev-server": "^2.8.2"
    "react-router-dom": "^4.2.2",
...

babel.rc:

{
  "presets": [
    ["es2015", {"modules": false}],
    "stage-2",
    "react"
  ],
  "plugins": [
    "react-hot-loader/babel"
  ]
}

webpack.config.js:

const path = require('path');
const webpack = require('webpack');

module.exports = {
  devtool: 'eval',
  entry: [
    'babel-polyfill',
    'react-hot-loader/patch',
    'webpack-dev-server/client?http://192.168.1.33:3000',
    'webpack/hot/only-dev-server',
    './app/index.js'
  ],
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, '../dist'),
    publicPath: '/static/'
  },
  module: {
    rules: [
      {test: /\.(jsx|js)$/, loader: 'babel-loader', exclude: /node_modules/},
    ],
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
  ],
  devServer: {
    host: '192.168.1.33',
    port: 3000,
    historyApiFallback: true,
    hot: true,
    compress: true,
  }
};

All starting with yarn webpack-dev-server --host 192.168.1.33 .I'm using AppContainer from gaeron's react-hot-loader and module.hot.accept from webpack HMR in entry point index.js:

import React from 'react';
import ReactDOM from 'react-dom'
import {AppContainer} from 'react-hot-loader'
import Nav from './navigation';

const rootEl = document.getElementById('root');
const render = Component => {
  ReactDOM.render(
    <AppContainer>
      <MuiThemeProvider>
        <Component/>
      </MuiThemeProvider>
    </AppContainer>,
    rootEl
  )
};

render(Nav);

if (module.hot) {
  module.hot.accept('./navigation', () => {
    const Nav = require('./navigation').default; //working same without this row
    render(Nav)
  })
}

All routig coming from next component - ./navigation.index.js:

import React from 'react';
import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';
import IconButton from 'material-ui/IconButton';
import Main from '../menu/index';
import PredTable from '../tablo/predTable';
import Confs from '../configs/confs';
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'

let routes = [
  {
    exact: true,
    path: '/',
    main: () => <Main/>
  },
  {
    path: '/Conf',
    main: () => <Confs/>
  }
];


function requireAllDataNames(requireContext) {
  return requireContext.keys();
}

const FileNames = requireAllDataNames(
  require.context('../../../src/data', false, /.json$/)
);

const Auth = (props) => (
    <PredTable id={props['props']}/>
);

export default class Nav extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      props: []
    };
  }

  getLink(file) {
    let id = file.substring(2, file.length - 5);
    return <Link to={'/' + id} key={id}>{id}</Link>
  }

  getRoute(file) {
    let id = file.substring(2, file.length - 5);
    return <Route 
      path={'/' + id} 
      key={id} 
      component={(props) => <Auth props={id} {...props} />}
    />
  }

  render() {
    return (
      <Router>
        <div style={{display: 'flex'}} ref="nav">
          <Drawer
            docked={true}
            width={200}
          >
            <Link to='/' key="main">Меню</Link>
            <Link to='/Confs' key="conf">Settings</Link>
            {FileNames.map((v) => (
              this.getLink(v)
            ))}
          </Drawer>
          <div style={{flex: 1}}>
            {routes.map((route, index) => (
              <Route
                key={index}
                path={route.path}
                exact={route.exact}
                component={route.main}
              />
            ))}
            {FileNames.map((v) => (
              this.getRoute(v)
            ))}
          </div>
        </div>
      </Router>
    );
  }
}

Importing two main components in predTable:

import React from 'react';
import Table from '../table/table';
import Clock from '../clock2';


export default class PredTable extends React.Component {

  constructor(props) {
    super(props);
    let Config = require('../../../src/configs/' + props.id + '.json');
    this.state = {
      id: props['id'],
      conf: Config
    }
  }


  render() {
    return (
      <div>
        <Table tableId={this.state.id}/>
        <Clock size={350} tableId={this.state.id} timeFormat="24hour" hourFormat="standard"/>
      </div>
    );
  }
}

In Table component from ../tablo/table I importing json file, and when something changing in this file I've got this messages in console:

[WDS] App updated. Recompiling...
[WDS] App hot update...
[HMR] Checking for updates on the server...
[HMR] Updated modules:
[HMR]  - ../src/data/2.json
[HMR]  - ../src/data recursive ^\.\/.*\.json$
[HMR]  - ./app/table/table.js
[HMR]  - ./app/table/predTable.js
[HMR]  - ./app/navigation/index.js
[HMR] App is up to date.

So it seems that app hot-reloading is working, but it reload all component in path from parent Nav with routing, to PredTable and Table. But with predTable refreshing also refreshing component Clock, that imported into it. And it is something I wanna avoid.

So the question is - How can I update ONLY ONE component - Table, not the entire path of components Navigation-PredTable-Table?


In some JS react chat i've got messages, that it is normal behavior for HMR. Reloading all parent Components. Changing data.json.

For structure example:

-index.js  
--navigation.js (**reloaded**. Start or Routing, reloaded cause have predTable,js, that contain table.js with imported data.json)  
---predTable.js (**reloaded**. contain table.js with imported data.json)    
----table.js (**reloaded**. imported data.json. I wanna that only **THIS** component reloading)      
---->data.json (import)    
----clock.js  
---conf.js  
---multiTable.js (reloading cause call table.js inside, BUT! with different data3.json)  
---->table.js  
------data3.json  
0

There are 0 answers