Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question] Example of new context API in use #649

Closed
rlueder opened this issue Oct 25, 2018 · 13 comments
Closed

[question] Example of new context API in use #649

rlueder opened this issue Oct 25, 2018 · 13 comments

Comments

@rlueder
Copy link

rlueder commented Oct 25, 2018

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!

@daniel-hauser
Copy link
Contributor

event.target is the map

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

@rlueder rlueder closed this as completed Nov 8, 2018
@redbmk
Copy link
Contributor

redbmk commented Apr 12, 2019

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?

@redbmk
Copy link
Contributor

redbmk commented Apr 12, 2019

btw I found a solution here: #691 (comment)

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

@rlueder
Copy link
Author

rlueder commented May 13, 2019

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

@nathanredblur
Copy link
Contributor

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>'

@mklopets
Copy link
Collaborator

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

@redbmk
Copy link
Contributor

redbmk commented Jan 28, 2020

@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)

@nathanredblur
Copy link
Contributor

nathanredblur commented Jan 30, 2020

@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 />)
}

@redbmk
Copy link
Contributor

redbmk commented Jan 31, 2020

@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>
)

@tarim
Copy link

tarim commented Aug 6, 2020

Same issue here. Any solution, please?

@redbmk
Copy link
Contributor

redbmk commented Aug 6, 2020

@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>)

@zbyte64
Copy link

zbyte64 commented Jun 18, 2021

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

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

@redbmk
Copy link
Contributor

redbmk commented Jun 18, 2021

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants