foxhound87/rfx-core

The UI not update when hot-reload

njleonzhang opened this issue · 4 comments

enviroment:

    "mobx": "^3.2.2",
    "mobx-react": "^4.2.2",
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-router-dom": "^4.1.2",
    "rfx-core": "^1.5.3"

entry:

.....
import "./stores" // init the store

const store = rehydrate()
ReactDOM.render(
  <AppContainer>
    <Router>
      <Provider store={isProduction ? store : hotRehydrate()}>
        <App />
      </Provider>
    </Router>
  </AppContainer>,
  document.getElementById('app'))

// hot reload config
if (module.hot) {
	module.hot.accept(() => renderApp(App))
}

@withRouter // make react-router work 
@inject('store')
@observer
export default class App extends Component {
  constructor(props) {
    super(props)
    this.store = this.props.store.appState
  }

  componentDidMount() {
    this.store.setDate('2017-11-11')
  }

  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={img} className="App-logo" alt="logo" />
          <h2>Welcome to React {this.store.dateStr}</h2>
        </div>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload. {this.store.testVal}
        </p>
        ..........
    )
  }
}

Store:

export default class AppState {
  @observable testVal

  constructor() {
    this.testVal = '123'
  }
}

import { store } from 'rfx-core'

import AppState from './AppState'

export default store.setup({
  appState: AppState,
  ......
})

After updating Store, for example, change this.testVal = '123' to this.testVal = '1234', the log shows Store has changed, but the UI not updated.

image

Here is the sample project, would you please help to check?
https://github.com/njleonzhang/my-react-starter

fixed by myself

Please share your fix, can be useful for other users too

Sample project.

  1. for non rfx-core version: https://github.com/njleonzhang/my-react-starter
  2. for rfx-core version: https://github.com/njleonzhang/my-react-starter/tree/ssr-rfx-core

Points:

  1. In main.jsx, watch both App, and store
  module.hot.accept(['./components/App', './stores'], () => {
    const newApp = require('./components/App').default
    renderApp(newApp)
  })
  1. in App.jsx, importing store to make store a child component of App.jsx, so that when we change store code, the App.jsx can be triggered to run hot reload.
import '../../stores' // for hot-reload, make code change in store trigger App.jsx reload

rfx-core keeps current value of store when hot-reload. but when working with react-router, the hot reload will also trigger router, so if you change store in react hook componentDidMount, then the store value you kept through rfx-core will still be override by router. So in this scenario, the benefit of rfx-core (I mean keep state) becomes useless.

At the same time, rfx-core(keep state) can cause another side-effect. For example, I have a testVal = 123 in store, and when I change it to testVal = 1234, it seems the new value can not be updated to store. because the old value 123 is kept. (I am not sure if this is caused by my config)

I need react-router, and most of the time, I change store when router change(get data from server), kept store value is always override by router change in my project. so I remove rfx-core and use a normal store. this can work currently(not sure if will encounter other issues) with the next warning:

MobX Provider: Provided store 'store' has changed. Please avoid replacing stores as the change might not propagate to all children

So it seems there is no solution now to make hot-reload work perfect with mobx + react + react-router + mobx-react-router. A perfect solution need to keep current value, update changed value, at the same time not be override by router, hope react professional can make a solution. @foxhound87

Sorry for my poor english, hope can help or inspire someone.

Thanks for your effort!