使用redux ownProps在props中获取路由器路径

时间:2017-03-23 20:18:19

标签: reactjs redux react-router router react-router-redux

我正在尝试在容器中获取反应路由器的当前路径,以便将其传递给将改变其可见性过滤器的子组件。

更具体地说,我正在尝试使导航菜单突出显示当前活动的页面。

我正在使用react,redux,react-router和react-router-redux,所以我可以从redux商店访问路由器状态。

react-router-redux的文档中,它说要做这样的事情:

function mapStateToProps(state, ownProps) {
  return {
    id: ownProps.params.id,
    filter: ownProps.location.query.filter
  };
}

这是我的容器组件:

import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import {
  Segment as UISegment,
} from 'semantic-ui-react'
import NavMenu from '../components/NavMenu'

class MenuBar extends Component {
  static propTypes = {
    path: PropTypes.string.isRequired
  }

  render() {
    const { path, } = this.props

    return (
      <UISegment>
        <NavMenu activePath={path} />
      </UISegment>
    )
  }
}

const mapStateToProps = (state, ownProps) => {   
  return {
    path: ownProps.route ? ownProps.route.path : "/"
  }
}

export default connect(mapStateToProps)(MenuBar)

在NavMenu组件中,语义菜单组件将activePath与其自己的路径进行比较,并突出显示活动按钮。

一切似乎都在理论上起作用;当我点击菜单的不同部分时,会发出@@router/LOCATION_CHANGE动作。在redux dev工具中,我看到状态在变化。但是,永远不会调用mapStateToProps,并且永远不会重新呈现此组件。

有什么想法吗?我想过使用像shouldComponentUpdate这样的反应方法,但似乎反应甚至没有意识到状态或道具正在发生变化。

1 个答案:

答案 0 :(得分:3)

首先要注意的是,您实际上并未从商店访问路由器状态。如果您查看react-router-redux docs,它实际上会警告不要这样做

  

您不应直接从Redux商店读取位置状态。这是因为React Router异步操作(处理诸如动态加载的组件之类的东西),并且组件树可能尚未与Redux状态同步更新。你应该依赖React Router传递的道具,因为它们只有在处理完所有异步代码后才会更新。

您的容器正在从ownProps读取数据,这只是传递到该容器组件的道具。您引用的react-router-redux文档中的示例仅适用于顶级路由组件(作为组件prop传递给React Router Route组件的组件)。 React Router将路由器数据传递给所有路由组件。

在您的情况下,MenuBar是您的顶级路由组件的子级。你有两个选择

  1. 将您想要的数据从路径组件中向下传递到MenuBar。
  2. 使用React Router的withRouter更高阶组件将值注入MenuBar https://github.com/ReactTraining/react-router/blob/v3/docs/API.md#withroutercomponent-options
  3. 另外,我相信您要寻找的值是ownProps.location.pathname而不是ownProps.route.path

    选项1的一些代码,因为我假设MenuBar没有在组件树中嵌套太深:

    如果你的路线配置是

    <Router history={browserHistory}>
      <Route path="/" component={AppLayout}>
        <Route path="about" component={About}/>
        <Route path="users" component={Users}/>
        <Route path="*" component={NoMatch}/>
      </Route>
    </Router>
    

    你的AppLayout就像是

    const AppLayout = ({ children, location }) => {
      return (
        <div>
          <MenuBar path={ location.pathname } />
          { children }
        </div>
      )
    } 
    

    和MenuBar会收到您要查找的数据。