Skip to content

Instantly share code, notes, and snippets.

@jmorrell
Created September 10, 2015 04:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jmorrell/3d1c57ba926d3cc96b59 to your computer and use it in GitHub Desktop.
Save jmorrell/3d1c57ba926d3cc96b59 to your computer and use it in GitHub Desktop.
In the case of an autocomplete, the way we do it is to break it down into two components:
1. A completely dumb component that takes only props. This defines appearance, behavior, etc.
It may have it's own component local state, though that's part of the implementer's job to
decide. If something else anywhere on the page might care, it should be external and passed
in.
Ex: A dropdown component might choose to keep whether or not it's been expanded as local state.
This works, until you need to change something else on the page in response to the dropdown
being open.
This component should be reusable anywhere in your app as long as you have the data it needs to
render.
When the user interacts with it, it alerts the rest of the app through callbacks. It does not
fire its own actions.
2. A wrapper component that subscribes to the necessary stores and passes the necessary data and callbacks.
This component takes in few or no props and pulls in all the data it needs from stores. We refer to these
as containers.
So in the case of an autocomplete we might have something like:
```js
<Autocomplete
value={currentValue}
options={arrayOfOptions}
onTextChange={callback}
onSelectValue={callback}
{...propsThatChangeAppearance}
/>
```
And a specific component that's used in one / few places in your app that subscribes to stores:
```js
class MyAutocomplete extends React.Component {
static getStores() {
return [
// Whatever stores and data this autocomplete depends on
];
}
static calculateState(prevState) {
// pull the data out of the stores and massage it into what the component needs
// In this architecture, this is the only place that you pull data out of stores
}
render() {
return <Autocomplete {...this.state} />;
}
_onSelectValue(value) {
/* fire an action */
}
_onTextChange(value) {
/* fire an action */
}
}
module.exports = FluxContainer.create(MyAutocomplete);
```
This is using the FluxContainer from FB: https://github.com/facebook/flux/blob/master/src/FluxContainer.js
Mainly because I'm familiar with the API.
but you should probably use Redux, which will have a similar convention.
The UI and the data are now 100% separate, and each should be re-usable without the other.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment