React Router - 在一个route / enable子组件下呈现两个组件仍然可以访问params?

时间:2017-07-31 22:21:29

标签: javascript reactjs react-router react-redux

My React Router thingy看起来像这样:

<Switch>
  <Route path='/posts/:id' component={PostsView} />
  <Route exact path='/' component={Home}/>
  <Route component={NotFound}/>
</Switch>

我现在想要实现一个AudioPlayer并在同一页面上显示它。

我当然可以导入AudioPlayer中的PostsView并从那里渲染它。但是,我认为不混合两个组件会更好,更纯粹,但是在第三个组件中将它们放在另一个组件中,这三个组件都会呈现它们,并且只负责在屏幕上显示内容。

我试图这样做,但是我被卡住了,因为我的帖子组件需要路由/posts/:id,所以我不能把它放在第三个组件中。我试过这样的事情:

<Switch>
  <Route path='/sentences/:id' component={Main} />
  <Route exact path='/' component={Home}/>
  <Route component={NotFound}/>
</Switch>

然后在Main我试过了:

render() {
    return (
      <div>
        <PostsView />
        <AudioPlayer />
      </div>
      );
  }

...但这似乎是错误的方法,因为反应路由器出现了问题!结合这两个组件最合理的方法是什么,并保持我的路由完好无损?

1 个答案:

答案 0 :(得分:0)

如果音频播放器是全局播放的,并且播放某些并且始终与应用中当前显示的内容无关,那么您可能需要考虑移动某些内容到像redux这样的全球商店。当您选择要播放的内容时,您可以通过操作更新redux,在AudioPlayer内,您可以监听商店中的更改并进行相应调整。

import { setCurrentlyPlaying } from "actions"

class SomeComponent extends React.Component {
  onClickTrack = (track) => {
    this.props.setCurrentlyPlaying(track)
  }
}

export default connect(null, { setCurrentlyPlaying })(SomeComponent)

此随机组件通过redux设置当前播放的曲目 - 您还可以将操作调整为添加到播放列表等。

在audioplayer中

class AudioPlayer extends React.Component {
  componentWillReceiveProps(nextProps) {
    const nextTrack = nextProps.track
    const currentTrack = this.props.track

    if (nextTrack !== currentTrack) {
      // do something
    }
  }

  shouldComponentUpdate(nextProps) {
    const nextTrack = nextProps.track
    const currentTrack = this.props.track

    if (nextTrack !== currentTrack) {
      // do something
    }
  }

  render() {
    return (<audio src={this.props.track.src}/>)
  }
}

export default connect(
  (state) => {
    return { track: state.currentlyPlaying }
  }
)(AudioPlayer)

你可以通过多种方式做到这一点。我不确定audio元素将如何对重新渲染做出反应(我自己从未使用过该元素),因此您可能必须实现shouldComponentUpdate并确保不更新组件,除非你需要。

这样做,您将拥有一个全局“容器”,它将显示AudioPlayer和React Router。

<div>
  <Switch>...</Switch>
  <AudioPlayer/>
</div>

编辑,如果您要么a)不介意传递回调以设置要播放的曲目并在共同的父级中维护此曲目,则不需要redux

class Parent extends React.Component {
  state = { currentlyPlaying: null }

  setCurrentlyPlaying = (track) => {
    this.setState({ currentlyPlaying: track })
  }

  render() {
    return (
      <div>
        <Child setCurrentlyPlaying={this.setCurrentlyPlaying}/>
        <AudioPlayer currentlyPlaying={this.state.currentlyPlaying}/>
      </div>
    )
  }
}

或b)使用context提供回调 - 我不建议这样做,因为即使React的维护者建议不要使用上下文。我不熟悉上下文,所以如果你想这样做,你需要查看如何做。