Last active
July 12, 2022 15:03
-
-
Save phyllisstein/1e56ec9fc7945f934751df87aa2dd121 to your computer and use it in GitHub Desktop.
Two patterns for sharing MapStack UI.
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
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ⭑ Approach Two ⭑ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | |
// ~~~~~~~~~~~~~~~~~~~~~ Component Components Component ~~~~~~~~~~~~~~~~~~~~~ // | |
/** | |
* Our package exposes a number of React components purpose-dedicated to | |
* building a map; the downstream app composes the React components we expose. | |
* The Unison component, not our code, would call ReactDOM::render. This is the | |
* pattern one normally sees with React libraries. | |
*/ | |
import { MapsStack, Map, Pin } from '@voxmedia/maps-ui' | |
import ReactDOM from 'react-dom' | |
ReactDOM.render( | |
<MapStack> | |
<Map> | |
<Pin id='7c75fa4c-edf0-4dab-9d2c-aa8c9d0afd9d' /> | |
</Map> | |
</MapStack>, | |
document.querySelector('.container'), | |
) | |
/** | |
* When the state of the page changes, the downstream app changes the data on | |
* our React components. | |
*/ | |
<Pin focused={ !isFocusedNow } id='7c75fa4c-edf0-4dab-9d2c-aa8c9d0afd9d' /> | |
/** | |
* React doesn't need to own the entire page to handle state and offer hooks for | |
* callbacks. | |
*/ | |
<MapProvider data={{ venueID: '7c75fa4c-edf0-4dab-9d2c-aa8c9d0afd9d', mapKind: 'territory' }}> | |
<MapStack> | |
<Map onMoreMaps={ () => {} }> | |
<Pin id='7c75fa4c-edf0-4dab-9d2c-aa8c9d0afd9d' /> | |
</Map> | |
</MapStack> | |
</MapProvider> | |
/** | |
* Conceivably, this opens up a larger surface for the downstream app to break | |
* something. It also asks downstream teams to work in JSX which is not always | |
* familiar. Nor are React's declarative design idioms; nor its funkier new | |
* features, like hooks. | |
* | |
* HOWEVER. We also vastly widen the possibilities for our team and others to | |
* play with and iterate on the map. This is broadly more good than the risk of | |
* bugs is bad. Shifting to a declarative pattern for state changes feels | |
* appetizing after struggling for only a few days with imperative updates in | |
* Backbone. And dropping this fuzzy intermediary message broker (that is, the | |
* wrapper class) keeps our focus on the component layer---a piece we were going | |
* to bulid anyway. | |
* | |
* You may have surmised that I talked myself into this one as I typed the | |
* differences out loud. I did. Disagree with me! | |
*/ |
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
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Approach One: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Wrapper Class ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // | |
/** | |
* Our package exports a single wrapper class. It wraps all the functionality of | |
* mapping application. We new it up in a Unison component, passing a selector, | |
* and hand over rendering the map. | |
* | |
* (This is not all that different from how Backbone works. We'll get back to | |
* that in a bit.) | |
*/ | |
import MapStack from '@voxmedia/maps-ui'; | |
const mapStack = new MapStack('.container') | |
/** | |
* When the state of the page changes, we call methods on the wrapper instance | |
* to true up the rendered map. | |
*/ | |
// View#onScroll... | |
mapStack.focusPin('7c75fa4c-edf0-4dab-9d2c-aa8c9d0afd9d') | |
// View#onResize... | |
mapStack.setSize(window.innerWidth, window.innerHeight) | |
/** | |
* The wrapper is an event emitter. The Unison component listens for its events | |
* and shunts them to the appropriate bits of SBN. | |
*/ | |
mapStack.on('affiliateClick', () => { | |
this.analytics.moneyPixel(); | |
}) | |
/** | |
* Hiding most of the view's implementation could make it easier to iterate on | |
* the component layer faster. As long as the SBN page knows MapStack#focusPin | |
* will focus on a pin, it doesn't need to know how the pin gets focused. | |
* Closing over the UI also means we keep tighter control over the look and feel | |
* of the map. | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment