fetching data before changing route with react-router

邮差的信 提交于 2019-12-04 19:35:48

if you're using plain redux and router you can use router's lifecycle functions like onEnter (which is calling before entering the view) or onLeave..., then you can do whatever you like and these are accept an callback function when you call it, actual routing happens.

another option is using some redux promise middleware for async jobs such as redux-promise-middleware or simply thunk with loadingbar (as we use them in production) which is works perfectly with async actions.

Redux Promise Middleware

React Redux Loading Bar

Here is an example without 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>

This is better handled in the HomePagecomponent where the server call is made. You need to set a state that indicates the call is being processed e.g this.state.loading or this.state.processing and then you can show/hide a loader or the bar based on the value of these. E.g

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>
  )
 }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!