【问题标题】:React Router Link doesn't work with LeafletJSReact Router Link 不适用于 LeafletJS
【发布时间】:2017-04-18 06:51:46
【问题描述】:

版本:

  • react-router-dom 4.1.1
  • react-router-redux 5.0.0-alpha.4
  • 反应传单 1.1.3
  • 传单 1.0.3

重现步骤

我创建了一张传单地图。我在其中添加了一些标记。这些标记有弹出窗口。 在每个弹出窗口中,我都希望有一个<Link>

如果有帮助,这是我的路由配置:

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

预期行为

当弹出窗口打开时,我可以看到我的链接并点击它。

实际行为

无法看到链接。它没有生成。

额外细节

在我的&lt;MapMode&gt; 中,我使用传单中的&lt;Map&gt;。 如果我在&lt;Map&gt; 标签上方设置&lt;Link&gt;,它就可以工作。 只要我想在我的&lt;Map&gt; 中有一个链接,它就会以某种方式中断。 这是我页面的 React 结构,&lt;Popup&gt; 标签只包含 null,因为 Javascript 正在破坏:

这是一个相当复杂的问题,所以请随时向我提问。 谢谢。

【问题讨论】:

  • 传递给 ConnectedRouter 的 history 是否有价值?看起来它是未定义的。
  • @Panther 不,如果您查看 React 结构,它就有价值。此外,如果我在 上方设置一个链接,它工作正常。 React-router 贡献者建议它可以链接到 LeafletJS 创建一个门户? github.com/ReactTraining/react-router/issues/… 不知道我怎么能避免这种情况:(

标签: javascript reactjs leaflet react-router react-leaflet


【解决方案1】:

我尝试了 Tharaka 建议的解决方案,但它对我不起作用。看起来 react-leaflet 的 Popup 正在使用它自己的上下文,因此阻止了从更高级别传递的上下文。然而,受此解决方案的启发,我想出了另一个非常简单且基于组合原则的解决方案。

我创建了 RouterForwarder 组件

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

然后以下列方式在我的组件(呈现地图、标记、弹出窗口和链接的组件)中使用它:

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,
}

【讨论】:

  • 我无法让选定的答案起作用,但这对我有用。谢谢!
  • 感谢 Tharaka,我认为这种改进和更简单的解决方案在大多数情况下会更好。
【解决方案2】:

我不能 100% 确定这个答案。但无论如何我都会尝试,因为我认为至少它可能会为将来尝试解决此问题的任何人提供一些启示。

我在react-leaflet GitHub 存储库中从this issue 得到了第一个提示。根据那个和你的错误,问题似乎是Popup无法从context访问router,因为context没有以它们呈现的方式传递到Popup。因此,如果我们可以将上下文显式传递给 Popup,我们应该能够解决问题。

然后我在this StackOverflow 答案中找到了一种将上下文显式传递给组件的方法。有了这个,我认为你应该能够使用如下的 HoC(高阶组件)来解决你的问题。

这是向组件注入上下文的 HoC:

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;
}

假设您在一个名为 MapMaker 的组件中使用 Popup。然后你可以像这样使用 HoC 将带有router 的上下文注入到 Popup 中。

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
    );
  }

}

【讨论】:

  • 完美!我刚刚创建了一个LinkWithContext 而不是PopupWithContext,它对我有用!非常感谢:)
【解决方案3】:

我的解决方案(这是一种解决方法,但效果很好,我认为没有缺点):

我通过使用 (in react router v3 with redux)解决了

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

goTo

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

【讨论】:

    猜你喜欢
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 2016-08-30
    • 1970-01-01
    相关资源
    最近更新 更多