DO's:
- Use explicit contracts to pipe data & events between systems
- Business rules should bubble towards the top, UI and semantics should sink towards the bottom
DONT's:
- Prescribe a single design pattern
- Use jQuery as a crutch
- Be a fundamentalist
- Only change state on the components that need to be re-rendered
- Use ref=<name> to access the component from the parent
- All components should be instantiated inside a render() call; avoid storing components in state
- Define a key for items in a list
Use ternary operator with null to conditionally render:
<div>{this.state.verified ? <i className="verified"/> : null}</div>
Use map to programmatically render children:
<ul> {
_.map(this.state.items, function(item, index) {
return <li key=index>{item}</li>
})
}</ul>
| Props: | represents the overall application state. |
|---|---|
| State: | represents the individual state of a component. |
| Props: | configures how the application is to be rendered. |
| State: | configures how the component is to be rendered. |
Where to use the methods:
| setProps(): | can only be called on a root component. |
|---|---|
| setState(): | should only be called by the component itself. |
| set<Name>(): | should be defined on a component that allows for its state to be modified externally. |
Example public set state method:
setValue: function(val) {
this.setState({value:val})
}
Avoid direct API calls from components.
Use channels or event streams to pipe data into components
- Event streams: https://baconjs.github.io/
- Channels: https://github.com/postaljs/postal.js
| componentWillMount(): | bind event stream to component state |
|---|---|
| componentWillUnmount(): | unbind component from an event stream |
Example Data Binding:
componentWillMount: function() {
var self = this;
this.site_sub = channel.subscribe("CRUD.site."+this.props.site_id, function(data) {
self.setState({site: data.site})
})
},
componentWillUnmount: function() {
if (this.site_sub) {
this.site_sub.unsubscribe();
this.site_sub = null;
}
}
- Use on<event> properties to pipe events to functions that modify other components
- If a component modifies a component that is not in its refs, try to use a callback instead
Slug field example:
<input type="text" name="name" onChange={function() {self.refs.slug.setValue(event.target.value)}}/>
<SlugField name="slug" ref="slug"/>