将 Link 添加为具有 ReactDOM.render 的路由器的子级会产生 "You should not use <Link> outside a <Router>"

Adding a Link as a child of a Router with ReactDOM.render yields "You should not use <Link> outside a <Router>"

我正在寻找一种使用 ReactDOM.render 在反应路由器中创建 Link 的方法。设置大致如下所示:

const router = (
  <div>
    <Router>
      <Route path="/map" component={Map}/>
    </Router>
  </div>
);

Map.jsx 的相关部分如下所示:

const MapPopup = () => {
  return (
    <Link to={`/map/add`} />
  )
}

class Map extends React.Component {

  componentDidMount() {
    this.map = L.map('map')

    //...stuff...

    this.map.on('contextmenu', event => {
      popup
        .setLatLng(event.latlng)
        .addTo(this.map)
        .setContent(
          ReactDOM.render(
            MapPopup(),
            document.querySelector('.leaflet-popup-content')
          )[0]
        )
        .openOn(this.map)
    })
  }


  render() {
    return (
      <React.Fragment>
        <div id="map" />
      </React.Fragment>
    )
  }
}

我基本上是想在 leaflet 提供的地图弹出窗口中添加一个 Link(我不能为这个项目使用 react-leaflet)。但是,如果我 return MapPopup 直接在渲染函数中工作(显然不在弹出窗口中,但 Link 确实以这种方式工作)。

<React.Fragment>
    <div id="map" />
    <MapPopup />
</React.Fragment>

有谁知道我该如何解决这个相当不寻常的问题?

我正在使用 "react-router-dom": "4.3.1"

这是预期的错误,因为 <Link> 组件期望祖先组件是路由器类型(<BrowserRouter><MemoryRouter><Router> ...),请参阅 this thread 了解更多详情。

对于你的方案来规避此限制,可以使用 ReactDOM.createPortal 而不是 ReactDOM.render:

<Route
    path="/popup"
    render={() => (
              <Popup>
                <div>
                  Some content goes here
                  <Link to="/map"> Back to map</Link>
                </div>
             </Popup>
          )}
/>

哪里

class Popup extends React.Component {
  render() {
    return ReactDOM.createPortal(
      this.props.children,
      document.querySelector("#link-render-div")
    );
  }
} 

Here is a demo供大家参考