Skip to content

Instantly share code, notes, and snippets.

@Robert-W
Created February 4, 2016 13:30
Show Gist options
  • Save Robert-W/7a1cde76e1d9edde1b93 to your computer and use it in GitHub Desktop.
Save Robert-W/7a1cde76e1d9edde1b93 to your computer and use it in GitHub Desktop.
Example of Using context in React with ES6 Classes to pass a reference to a map object around
import appActions from 'actions/AppActions';
import React, {Component, PropTypes} from 'react';
import {mapConfig} from 'js/config';
import EsriMap from 'esri/map';
class Map extends Component {
//- Define your context types here as static property
static childContextTypes = {
map: PropTypes.object
};
//- Define a method to get the context
getChildContext = () => {
return { map: this.map };
};
constructor (props) {
super(props);
//- IMPORTANT: Set map to an empty object so children can check if map.loaded has changed
this.map = {};
}
componentDidMount () {
this.map = new EsriMap(this.refs.map, mapConfig.options);
//- At this point, any children will have an empty map object, to make sure they receive it once it is created
//- fire off an action to trigger a change event, this will rerender and then this.context.map will be Esri's Map Object
this.map.on('load', appActions.mapUpdated);
}
render () {
return (
<div ref='map' className='map'>
<MapControls />
</div>
);
}
}
class MapControls extends Component {
//- Define the context that I will need
static contextTypes = {
map: PropTypes.object.isRequired
};
componentDidUpdate (prevProps, prevState, prevContext) {
//- I am logging this here to demonstrate that after appActions.mapUpdated fires this.context.map will contain Esri's Map Object
console.log(this.context.map);
//- Check if the map exists so you can create an esri component with it, here im looking for a change in the loaded property
let {map} = this.context;
let {prevMap} = prevContext;
if (prevMap.loaded !== map.loaded) {
// We are Ready
}
}
}
@Robert-W
Copy link
Author

Robert-W commented Feb 4, 2016

Putting this up as an example. Context is a changing API as React's core team still seems to be evolving it until they can determine a Public API that works with everything.

One Catch

Right now componentShouldUpdate is a good way of manually pruning the tree recalculation, but this can cause issues. If your component declares context, it will receive prevContext as a third parameter and can check it, if not, then it wont. So things similar to pureRenderMixin won't work. Consider this:

<Parent>
  <Middle>
    <Child />
  </Middle>
</Parent>

If parent declares context, but middle does not, and child depends on context, this can be difficult if context changes. If Middle uses shouldComponentUpdate and returns true, the child wont receive the updated context. We also don't want Middle to be aware of it's children as that would complicate things. So you should be careful using context for something like a Map because if the map changes, and a middle component implements shouldComponentUpdate, it may prevent a child from getting the updated context.
See here for more: facebook/react#2517

An alternate solution

Create the map the same way and pass it as props, this is also a little painful as all middle components must explicitly pass props down and the map is mutable so detecting changes on it in shouldComponentUpdate will be difficult anyway

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment