- 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
orpage
).
- 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));
, theAsyncComponent
will render the proper view base on thestate
.
- 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.