erikras / react-redux-universal-hot-example

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

How to dispatch action client side only? #971

Open AndrewRayCode opened 8 years ago

AndrewRayCode commented 8 years ago

I need to call some specific actions on my client side only. Specifically I need to make some ajax calls only on client side page load. I also need to call a deserialize function to convert the loaded server data into some class based data objects.

It seems like when using the decorator @connectData( fetchData, fetchDataDeferred ) neither function is called on the server side on first page load.

The Widgets page mentions "This uses the static method fetchDataDeferred" but that method isn't real.

skywickenden commented 8 years ago

@connectData Definitely did run on the server on first page load, however it has recently been replaced with @asyncConnect. See #531. Might you mixing up different versions?

AnuragSinghTomarr commented 8 years ago

hi iam using @asyncConnect([{ deferred: true, promise: ({store: {dispatch, getState}}) => { return dispatch(loadHotKey()); } }]) here i am making a call to loadHotKey API. But i also want to make some another API call after this lets say XYZ API. So can you please let me know what changes i need to make in mine above code

AndrewRayCode commented 8 years ago

@skywickenden

Might you mixing up different versions?

https://github.com/erikras/react-redux-universal-hot-example/blob/c5fe73827282f249853c530197c945daa67c34b4/src/containers/Widgets/Widgets.js#L60

"This uses the static method fetchDataDeferred"

AnuragSinghTomarr commented 8 years ago

Than if i have to use fetchDataDeferred, than why this repo has been using @asyncConnect in the widget.js @asyncConnect([{ deferred: true, promise: ({store: {dispatch, getState}}) => { if (!isLoaded(getState())) { return dispatch(loadWidgets()); } } }]) and dispatching action loadWidget to make an API call

AndrewRayCode commented 8 years ago

@AnuragSinghTomarr I think it's text that wasn't updated after the commit was made. The method doesn't exist anymore.

One thing that's frustrating here is I'm trying to do a client side only call, but the version of the repo I started from uses redux-router and now it seems like an entirely different package react-router-redux is used so the migration path is very complicated.

AnuragSinghTomarr commented 8 years ago

Yes migration is some how complicated if you are mid of your project. Although i was too on the previous version of the repo just migrated to the new one a couple of days back as i was facing some redirection issue after API call and based on conditions want to redirect so just i gave a try to the new repo.

AndrewRayCode commented 8 years ago

Also this boilerplate project uses an api flag that doesn't exist https://github.com/erikras/react-redux-universal-hot-example/blob/c5fe73827282f249853c530197c945daa67c34b4/src/containers/Widgets/Widgets.js#L11 ping @sars

As far as I can tell it's impossible to trigger a client-only action using redux-async-connect.

skywickenden commented 8 years ago

To do something on the client only simply wrap it in

if(__CLIENT__){
  // code here
}

Be careful not to do anything that would cause the server side render to be different from the client sides initial render or the server side render will be discarded.

AndrewRayCode commented 8 years ago

@skywickenden that code still does not execute on first client side page load. It only executes when navigating away and back.

skywickenden commented 8 years ago

How about putting this in a top level component that never reloads, such as App.js

componentDidMount() {
  if(__CLIENT__){
    // code here
  }
}
skywickenden commented 8 years ago

Alternatively, if it needs to run in a nested component, and you don't want the flag in in the redux state.

componentDidMount() {
  if(__CLIENT__ && this.state.alreadyLoaded === false){
    // code here
    this.setState({alreadyLoaded: true});
  }
}