React Router + Redux - 在路由更改时调度异步操作?

时间:2016-05-24 07:05:35

标签: javascript reactjs react-router redux

我有一个使用redux和react-router的通用反应应用程序。

我有以下几条路线:

/2016
/2015
/2014
/2013

每条路线都需要来自API的数据。目前,我在导航组件中有<Link>个元素调度异步操作onClick,该操作使用来自该路由的API的数据填充商店。

对于MVP,我只是在路由更改时用新帖子内容覆盖商店中的post: {}内容,这样我们就可以获得API上的任何新内容。

我已经意识到在<Link>按钮上设置操作调度程序并不是最佳选择,因为按下后退按钮不会重新触发操作调度以获取上一个路由的内容。

有没有办法让React Router在路由发生变化时随时触发调度操作? (限制它听一组特定的路线将是一个奖励)。

我意识到我应该从商店获取历史记录,但就目前而言,通过触发行动调度以获取新内容,再次点击API会更容易。< / em>的

干杯。

3 个答案:

答案 0 :(得分:11)

React-router 4中已删除了“生命周期”钩子onEnteronChange,这使该问题的大多数其他答案都已过时。

虽然我建议您使用组件生命周期方法实现目标,但这是您的问题的答案,该问题适用于React-router 4。

今天有效的方法是使用由React路由器的开发人员自己创建的History library来监听历史更改,并从那里调度异步操作。

// history.js
import createHistory from "history/createBrowserHistory"

const history = createHistory()

// Get the current location.
const location = history.location

// Listen for changes to the current location.
const unlisten = history.listen((location, action) => {
    //Do your logic here and dispatch if needed
})

export default history

然后将历史记录导入到您的应用程序中

// App.js
import { Router, Route } from 'react-router-dom';
import Home from './components/Home';
import Login from './components/Login';
import history from './history';

class App extends Component {
  render() {
    return (
      <Router history={history}>
        <div>
          <Route exact path="/" component={Home} />
          <Route path="/login" component={Login} />
        </div>
      </Router>
    )
  }
}

来源:History library React router docs

答案 1 :(得分:8)

是的React路由器有onEnter和onLeave挂钩。您可以构建路由以获取store实例,以便可以在这些帮助程序中访问它:

const createRoutes = (store) => {
  const fetchPosts = () => store.dispatch({
    types: ['FETCH_POSTS', 'FETCH_POSTS_SUCCESS', 'FETCH_POSTS_FAIL',
    url: '/posts'
  });

  return (
    <Route path="/" component={App}>
      <Route path="posts" component={PostList} onEnter={fetchPosts}/>
      <Route path="posts/:id" component={PostDetail} />
    </Route>
  )
}

更好的解决方案是使用redialredux-async-connect之类的内容。这允许您将组件的数据依赖性与组件共同定位,同时保留在不触及网络的情况下测试组件的能力。

修改:这适用于旧的,不再受支持的react-router版本。

答案 2 :(得分:1)

我更喜欢从渲染道具本身分派动作:

<Route to="path" render={ props => {
  this.props.toggleInfoLayer(true);
  return <UserInfo />;
}} />

这是假设您正在使用Redux的mapDispatchToProps参数。

我尝试使用接受的答案中提到的历史记录更改事件处理程序,但是我发现不希望从恶意文件中分派动作。当Redux已经提供了太多的东西时,我不得不考虑的另一个地方。