在使用 react-router 更改路由之前获取数据

fetching data before changing route with react-router

我正在使用 reactreact-routerredux laravel 在后端,我正在使用所有最新版本,实际上我对这些还很陌生,我只是决定我应该将我的开发经验提升到一个新的水平并决定根据我的喜好使用它们,很多

我有以下问题:当我在 about-us 路线时,我然后点击 Home 但在路由器呈现之前首页,需要异步调用服务器。我注意到理论上我需要它是异步的,因为它需要在继续下一条路线之前完成。

然后,我想在页面顶部有一个栏,指示我正在获取服务器上的依赖项。完成后,它应该继续前往 主路线

一个实际的例子是GitHub,例如你在代码选项卡,然后你点击了问题选项卡,一个蓝色的加载栏将出现在页面的最顶部,表示正在获取数据或依赖项,一旦完成,它将呈现下一个路由。我该怎么做?

我想我应该使用某种中间件,所以在路由更改之前,我应该发送一个操作来获取我需要的依赖项,然后一旦完成我应该发送一个操作来更新某些部分在 redux 商店中,我找不到将中间件应用到 react-router 的方法,而且我真的不知道从哪里开始以及如何开始。

这在进行服务器调用的 HomePage 组件中处理得更好。您需要设置一个状态来指示正在处理呼叫,例如 this.state.loadingthis.state.processing,然后您可以 show/hide 加载程序或基于这些值的栏。例如

export default class Home extends React.Component {
 constructor(props) {
  super(props)
   this.state = {processing: false}
 }
 getData(){ //method that makes the server call
  ...//make the call to the server
  this.setState({processing: true})
  //check that the server call returns something and transition to next page when data is returned
 }

 render() {
  return (
   <div>
    {this.state.processing ? "return the loader image" : "else maybe return null"}
    <div>content of the home page</div>
   </div>
  )
 }
}

如果你使用普通的 redux 和路由器,你可以使用路由器的生命周期函数,如 onEnter(在进入视图之前调用)或 onLeave...,然后你可以做任何你喜欢的事情,当你调用它时,这些是接受回调函数,实际路由发生。

另一种选择是将一些 redux promise 中间件用于异步作业,例如 redux-promise-middleware 或简单地使用 thunkloadingbar(因为我们在生产中使用它们)与异步操作完美配合。

Redux Promise Middleware

React Redux Loading Bar

这是一个没有 redux 的例子:

MyPage.jsx

import React from 'react'
import { fetchDataForMyPage } from './someApi'

let data = {}

export default class MyPage extends React.Component {
    constructor() {
        super()
        this.state = {
            /* ... */
            data: data
            /* ... */
        }
    }
    render() {
        /* ... */
    }
    static loadData(routerParams, callback) {
        fetchDataForMyPage(routerParams).then((fetchedData) => {
            data = fetchedData
            callback()
        })
    }
    componentWillReceiveProps() {
        this.setState({
            data: data
        })
    }
}

Routes.jsx

import React from 'react'
import { Route } from 'react-router'
import App from './components/App'
import MyPage from './components/MyPage'

const loadDataOnEnter = (nextState, replace, callback) => {
    const nRoutes = nextState.routes.length
    const component = nextState.routes[nRoutes-1].component
    const params = nextState.params
    component.loadData(params, () => callback())
}

module.exports =
    <Route path="/" component={App}>
        <Route path="mypage/:param1" component={MyPage} onEnter={loadDataOnEnter} />,
        <Route path="anotherpage" component={AnotherPage} onEnter={loadDataOnEnter} />,
        <Route path="somepath" component={SomePageWithoutDataPreloading} />
    </Route>