Skip to content

Instantly share code, notes, and snippets.

@khanghoang
Last active December 23, 2015 10:12
Show Gist options
  • Save khanghoang/e7cbbe80d2badebd19ec to your computer and use it in GitHub Desktop.
Save khanghoang/e7cbbe80d2badebd19ec to your computer and use it in GitHub Desktop.
How to handle async in React?

How to handle async in React (with Reflux) app?

Principles

  • All components are dump, they are just view and render from their props.
  • Logic handling should be done in Component Wrapper (we call it container or page).

Async Component

  • Provide the interface for subclasses.
  • The subclass need to implement the idealView(), errorView(), emptyView(), loadingView() or use the defined class decorators, e.g: javascript @defaultLoadingDecorator @defaultErrorPopupDecorator class Login extends AsyncComponent { // some magic happen }
- The subclass doesn't need to implement `render()`, it should implement method to get its `state` base on the `data` changes. For example:
```javascript```
getComponentState(data) {
  if (data.hasOwnProperty('form')) {
    return COMPONENT_STATE.IDEAL;
  }

  if (data.error) {
    return COMPONENT_STATE.ERROR;
  }

  return COMPONENT_STATE.LOADING;
}
  • When data changes, the subclass calls this.setComponentState(this.getComponentState(data));, the AsyncComponent will render the proper view base on the state.
  • The getComponentState(data) should be pure function
  • The implementaion: javascript import React from 'react';

window.COMPONENT_STATE = { LOADING: 'LOADING', ERROR: 'ERROR', IDEAL: 'IDEAL', EMPTY: 'EMPTY' };

class AsyncComponent extends React.Component { constructor(props) { super(props); }

setComponentState(state) { if (this.state) { this.setState({ _componentState: state });

  console.log('state is changed to ' + state);
}

}

// loadingScreen get loadingView() { console.log('Implementation is missing'); return (

); }

get idealView() { console.log('Implementation is missing'); return (

); }

get emptyView() { console.log('Implementation is missing'); return (

); }

get errorView() { console.log('Implementation is missing'); return (

); }

render() { switch (this.state._componentState) { case COMPONENT_STATE.LOADING: return this.loadingView(); break;

  case COMPONENT_STATE.IDEAL:
    return this.idealView();
    break;

  case COMPONENT_STATE.EMPTY:
    return this.emptyView();
    break;

  case COMPONENT_STATE.ERROR:
    return this.errorView();
    break;

  default:
    return (
      <div> Default </div>
    );
    break;
}

} }

export default {AsyncComponent, COMPONENT_STATE};


### Remaining problems
- There are still a lot of boilerplate code. (e.g: `subcrible()` and `unsubcrible()`) -> It should be done via decorator.
- Handle mutil stores listening.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment