Created
September 10, 2015 04:58
-
-
Save jmorrell/3d1c57ba926d3cc96b59 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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