React & AltJS — Basic Guidelines and Best Practises
Prerequisites: Basic understanding of React, AltJS and Flux architecture

Pages
Page is just a component, it serves as the entry points from each Route. Pages normally render only the Container Components but can also render other Pages (following example bellow). Pages also:
- Get URL parameters and pass them down as props.
- Setup context to pass down as props.
- Render on part of the screen a component that must be shown to all other children pages on same route.
class MyDashboardPage extends Component {static propTypes = {
children: PropTypes.node,
params: PropTypes.object,
};componentDidMount() {
document.title = 'Dashboard';
}render() {
const {
children,
params,
} = this.props;if (children) {
// renders child on dashboard route
// for e.g. /dashboard/reporting will render
// ReportingPage
return React.cloneElement(children, params);
} // render MyDashboardContainer
return (
<MyDashboardContainer
params={params.shouldScroll}
/>
);
}
}
Container Components
A Container is a component close to the top of the nested hierarchy that listens for events that are broadcasted by the Stores. It provides the glue code to get the data from the stores and to pass this data down as props on the chain of its descendants. Having one of these controllers governing any significant section of the page can uncouple data handle code from the data representation components.
The duty of the container component is:
- handle all the data fetching and communication with the stores, it then passes it down as props to its children;
- handle business logic
- trigger actions and manages its state
- DON’T call source directly, use an action instead
To bind stores, use AltJS’ AltContainer component or connectToStore Higher Order Component.
AltContainer Example
class MyFinanceContainer extends Component {
// only fetch for data when already mounted
componentDidMount() {
CreditCardActions.fetchCreditCardDetails();
BankActions.fetchBankDetails();
}
render() {
const {
bankId,
cardId,
} = this.props;
return (
<AltContainer
stores={{
creditCards: () => ({
store: CreditCardStore,
value: CreditCardStore.getCardById(cardId),
}),
banks: () => ({
store: BankStore,
value: BankStore.getBankById(bankId),
}),
}}
>
<MyFinanceSection />
</AltContainer>
);
}
}connectToStores Example:
class UserProfileContainer extends Component {static getStores() {
return [UserStore];
}static getPropsFromStores() {
const {
user,
loading,
} = UserStore.getState();
return { user, loading };
}render() {
const {
user,
loading,
} = this.props;
return (
<div>
<UserProfileSection user={user} />
<PageLoader loading={loading} />
</div>
);
}
}
Presentational Components
These components are children of Container Components and receive all the data from the containers and just present it without any additional processing. There is no business logic associated with these components are they are preferred to be stateless functional components i.e. they do not maintain any state of their own and re-render only when props coming from parent changes.
DO
- render data received as props
- handle user interactions through callback events
- must be pure functions/components
- prefer stateless functional components
- prefer flat props over objects in props
- eventually, a component that nests a few other together can have suffix of Section with its name
DON’T
- access Source or Actions
- set components on state (e.g render a list of component and set to the state)
- handle business logic
- render dynamic array assigning the array index as the item key attribute, use an ID instead (not applicable on React 15+)
- generate IDs for item keys on render (not applicable on React 15+)
- assign props to state
- use
.bind, use fat arrow ( => )instead for performant and clean code - duplicate state between Parent and Child components
Stores
They can be considered as simple key-value stores for application state. Any change in Stores re-renders the components listening to store for some value. There can be multiple stores for multiple domains or types of data which constitute application state.
DO
- hold data only related to the application state in stores
- store normalized data (parsed as per component interfaces) from APIs
- splits stores into domains (such as User, CreditCard, Bank)
- provide static getter methods
- clear state after logout (when it applies)
- get payload from the dispatcher and initialize Immutable Map/List/Set etc if needed
DON’T
- handle component logic into stores
- handle user interaction logic (such as the selected item or current item been shown, keep it in component state)
- duplicate state into many stores, keep a single source of Truth
- store components references. You can go to jail for this.
- have direct setter methods, only change state from dispatcher events
- handle UI logic (such as defining class name)
- update store with
setTimeout, all store changes must come from a dispatcher
Actions
It’s a Javascript object that describes what we want to do, and the data we need to do it. Stores listen to different actions who sometime call source/API or sometime dispatch with container generated data. This dispatched action and data can then be listened by multiple stores which change their state accordingly.
DO
- maps application actions
- dispatch events to stores
- consume sources
- use
generateActionsfor view actions (follow example below)
DON’T
- handle business logic
- change routes, do it in the Container
- use
.deferorsetTimeout
