React-mapbox-gl: [question] Example of new context API in use

Created on 25 Oct 2018  路  13Comments  路  Source: alex3165/react-mapbox-gl

Can we get a quick example of the new context API for those upgrading from react-mapbox-gl 3.9.x to 4.0.0?

In my case I'm doing the following:

class MyComponent extends React.Component<Props> {
    static contextTypes = {
        map: PropTypes.object.isRequired
    };
}

To then be able to access the map object to update the cursor type when hovering elements, e.g.

circleOnMouseEnter={event => {
    map.getCanvas().style.cursor = "pointer";
    onEnterFeature(event.features[0]);
}}

Thanks!

Most helpful comment

event.target is the map

circleOnMouseEnter={event => {
    const map = event.target;
    map.getCanvas().style.cursor = "pointer";
    onEnterFeature(event.features[0]);
}}

All 13 comments

event.target is the map

circleOnMouseEnter={event => {
    const map = event.target;
    map.getCanvas().style.cursor = "pointer";
    onEnterFeature(event.features[0]);
}}

I'm doing something similar in 3.x but trying to upgrade to 4.x and ran into the same issue. The difference is I'm trying to access the map from context and don't have an event to pull the map from. Is there any way to access the map context?

btw I found a solution here: https://github.com/alex3165/react-mapbox-gl/issues/691#issuecomment-481450427

Sounds like when #654 is solved it'll be a little easier to use withMap or MapContext, but for now you can get it via react-mapbox-gl/lib/context or react-mapbox-gl/lib-esm/context

If anyone ever lands here looking for help with context API, the docs now include a section on it:
https://github.com/alex3165/react-mapbox-gl/blob/master/docs/API.md#context-api

Is not possible to use the example with typescript:

<MapContext.Consumer>
      {(map) => {
        let layers = map.getStyle().layers;

      }}
</MapContext.Consumer>
Type '(map: Map | undefined) => void' is not assignable to type '(value: Map | undefined) => ReactNode'.
  Type 'void' is not assignable to type 'ReactNode'.ts(2322)
index.d.ts(305, 9): The expected type comes from property 'children' which is declared here on type 'IntrinsicAttributes & ConsumerProps<Map | undefined>'

@nathanredblur indeed, as the types say, the render prop function needs to return a ReactNode, not be a void function.

@nathanredblur If you want to use context, but don't want to render anything there, you can just return null in that function. You could also use hooks to access the map in a component: const map = React.useContext(MapContext)

@redbmk Awesome Idea!, I will try that. That shoul be in the documentation.
-------------------- few hours latter ---------------------
Not works, I get undefined, What did I do wrong?

const Map = () => {
  const map = React.useContext(MapContext)

  React.useEffect(() => {
    console.log(map)
  }, [map])
return(<Mapbox />)
}

@nathanredblur The component that's reading from the MapContext needs to be inside <Mapbox />. Mapbox will render MapContext.Provider with map as the value, and React.useContext pulls from MapContext.Consumer.

It should look more like this:

const ComponentThatRequiresMap = () => {
  const map = React.useContext(MapContext);

  React.useEffect(() => {
    console.log(map);
  }, [map]);

  return null;
}

const Map = () => (
  <Mapbox {...mapboxProps}>
    <ComponentThatRequiresMap />
  </Mapbox>
)

Same issue here. Any solution, please?

@tarim did the solution above not work for you? What issue are you having exactly? You should be able to import { MapContext } from 'react-mapbox-gl'

Then as long as your component is a child of a Mapbox component, you can either use the hook (const map = React.useContext(MapContext)) or use the consumer (<MapContext.Consumer>({ map }) => renderSomething(map)</MapContext.Consumer>)

Example doesn't work in typescript, get the following:

Property 'value' is missing in type '{ children: Element; }' but required in type 'ProviderProps<MapContextProps>'.  TS2741

@zbyte64 Any chance you could post a sample of what you're trying in something like codesandbox? Here's something I threw together based on the previous discussion, which seems to be working. You'll need to add your access token to make it work completely, but I'm not seeing that typescript error you are.

Was this page helpful?
0 / 5 - 0 ratings