如何使用react-router v4发送redux动作?

时间:2018-02-06 15:15:40

标签: javascript reactjs redux react-router

我正在尝试将react-router v4,react和redux结合起来。因为react-router跟踪URL,我选择将该状态保留在redux-model之外。

但是当react-router发生路由更改时,我仍然需要一种方法来调度redux动作。哪个地方最好?

我的第一次尝试是将它放在react-router的链接的onClick属性中:

render() {

  // link config
  const links = this.props.photo.album( album => {
    <Link key={album.name} 
             to=`/album/${album.name}`
             onClick={() => this.props.dispatchAction(album.name)} />
  })

  // route config
  return (
     <div>
         {links}
         <Route path={`/album/:albumName`} component={Album}/>
     </div>
  )
}

这个想法是,当用户点击链接时,dispatchAction()将更新redux状态,然后加载Album组件。

问题在于,如果用户直接导航到URL(例如/ album / a1),则永远不会调度该操作,因为从技术上讲,该链接从未被点击过。

因此我删除了链接的onClick部分,并将dispatchAction移动到了Album组件的生命周期方法:

class Album extends Component {
    // invoked when user navigates to /album/:albumName directly
    componentDidMount() {
        this.props.dispatchAction(this.props.match.params.albumName)
    }

    // invoked whenever the route changes after component mounted
    componentWillReceiveProps(nextProps) {
        if (this.props.match.params.albumName != nextProps.match.params.albumName) {
            this.props.dispatchAction(nextProps.match.params.albumName)
        }
    ....
}

现在,无论何时挂载Album组件或更改其属性,它都会调度redux-action。这是组合这些库的正确方法吗?

2 个答案:

答案 0 :(得分:0)

react-router-redux通过在您的商店中应用中间件来为您执行此操作,该中间件调度路由更改的操作,也适用于初始路由更改。这绝对是最干净的方法。

唯一的缺点是它仍然是alpha,但我们一直在使用它而没有任何问题。它也是react-router附加软件包repo的一部分。

答案 1 :(得分:0)

您可以创建一个自定义Route组件,在componentDidMount中调度您的操作:

class ActionRoute extends React.Component {
  componentDidMount() {
    const { pathname } = new URL(window.location.href);
    const [albumName] = pathname.split('/').slice(-1);
    this.props.dispatchAction(albumName);
  }

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

现在,只要加载路线,就会调度您的操作。可组合性FTW!。

附注:如果您使用ActionRoute作为参数化路线(例如/album/1/album/2),您还需要在componentDidUpdate中调度该行动作为如果您从/album/1导航到/album/2,则不会卸载/重新安装组件。