React Router Link not working with LeafletJS

Versions:

  • react-router-dom 4.1.1
  • react-router-redux 5.0.0-alpha.4
  • reactive sheet 1.1.3
  • sheet 1.0.3

Steps to reproduce

I am creating a brochure map. In which I add some markers. These markers have pop-ups. In each of these popups I want to have<Link>

Also if it helps, this is my routing config:

ReactDOM.render(
  <Provider store={store}>
    <div>
      <AppContainer />
      <ConnectedRouter history={history}>
        <div>
          <MenuContainer />
          <Switch>
            <Route path='/:area/:sport/list' component={ListContainer} />
            <Route path='/:area/:sport/map' component={MapContainer} />
            <Route path='/:area/:sport/rasp' component={RaspContainer} />
            <Route path='/:shortcode/details' component={StationDetailsContainer} />
            <Redirect exact from='/' to='/wellington/paragliding/list' />
            <Route component={NoMatch} />
          </Switch>
        </div>
      </ConnectedRouter>
    </div>
  </Provider>,
  document.getElementById('root')
)

      

Expected behavior

I see my link and click on it when the popup opens.

Actual behavior

Actual behavior The link could not be seen. It is not generated.

additional information

On the inside, <MapMode>

I use <Map>

the flyer. If I set <Link>

just above the tag <Map>

it works. As soon as I want to have a link inside mine <Map>

, somehow it breaks. This is the React structure of my page, the tag <Popup>

just contains null

when the Javascript breaks: React structure

This is a pretty tricky issue, so feel free to ask me questions. Thank.

+3


source to share


3 answers


I'm not 100% sure about this answer. But I'm going to try it anyway, because I think that at least it can shed some light on anyone who tries to fix this problem in the future.

I got my first tip from this issue in the react-leaflet

GitHub repo. Consistent with this and your error, it seems the problem is that the Popup cannot be accessed router

from context

because it is context

not passed to the Popup with how they display it. So we have to fix the problem if we can explicitly pass the Popup context.

Then I found a way to explicitly pass the context to the component in this StackOverflow answer. With that, I think you should be able to use HoC (higher order component) in the following way to solve your problem.

This is a HoC that injects context into a component:



function withContext(WrappedComponent, context){

  class ContextProvider extends React.Component {
    getChildContext() {
      return context;
    }

    render() {
      return <WrappedComponent {...this.props} />
    }
  }

  ContextProvider.childContextTypes = {};
  Object.keys(context).forEach(key => {
    ContextProvider.childContextTypes[key] = React.PropTypes.any.isRequired; 
  });

  return ContextProvider;
}

      

Let's say you are using a Popup inside a MapMaker component. Then you can insert the context using router

into the Popup using HoC like this.

class MapMaker extends React.Component {

  //......

  // This make sure you have router in you this.context
  // Also you can add any other context that you need to pass into Popup
  static contextTypes = {
    router: React.PropTypes.object.isRequired
  }

  render(){

    const PopupWithContext = withContext(Popup, this.context);

    return (
      //..... your JSX before Popup
      <PopupWithContext/> // with your props
      //..... your JSX after Popup
    );
  }

}

      

+3


source


I tried the solution Tharaka suggested, but it didn't work for me. It looks like the "tooltip" is using its own context, thereby blocking the context that is passed from higher levels. However, inspired by this solution, I came up with another one, very simple and based on the principle of composition.

I have created a RouterForwarder component

import React, { Component } from 'react'
import PropTypes from 'prop-types'

class RouterForwarder extends Component {
  getChildContext() {
    return this.props.context
  }

  render() {
    return <span>{this.props.children}</span>
  }
}

RouterForwarder.childContextTypes = {
  router: PropTypes.object.isRequired,
}

RouterForwarder.propTypes = {
  context: PropTypes.object.isRequired,
}

export default RouterForwarder

      



and then used it in my component (the one that displays Map, Marker, Popup and Link) like this:

import RouterForwarder from './RouterForwarder'

class MyComponent extends Component {

  render() {
    return (
    ...
      <Popup>
        <RouterForwarder context={this.context}>
          <Link to={'my destination'}>Go to My Destination</Link>
        </RouterForwarder>
      </Popup>
    ...)
  }
}

MyComponent.contextTypes = {
  router: PropTypes.object,
}

      

+10


source


My solution (this is a workaround, but works great and I don't see any drawbacks):

I decided to use (in the reply router v3 with a shortcut )

<a onClick={() => goTo(params)} />

      

whereas goTo

defined in

const mapDispatchToProps = (dispatch) => bindActionCreators({
  goTo(id) {
    return push(`/<url>/${id}`); // push from 'react-router-redux'
  },
}, dispatch);

      

-1


source







All Articles