Reputation: 1274
I'm using react, react-router, and redux with laravel on the backend and I'm using all the latest releases and I'm actually quite new to these, I just decided I should take my development experiences to the next level and decided to use these based on how I liked them, A LOT.
I have the following problem: When I am in the about-us route, I then click Home but before router renders the home page, it needs to make an async call to the server. I notice that I theoretically need this to be async because it needs to finish before proceeding to the next route.
Then, I want to have a bar on the top of the page that indicates that I am fetching dependencies on the server. Once it is done, it should proceed to the home route.
A practical example is GitHub, example you are on the code tab, then you clicked on the issues tab, a blue loading bar will appear on the very top of the page that indicates that data or dependencies are being fetched then once it's done it will render the next route. How do I do this?
I'm thinking I should use some kind of a middleware, so before the route change I should dispatch an action that will fetch the dependencies that I need then once it's done I should dispatch an action that will update some parts of the redux store, I can't find a way to appy a middleware to react-router though and I really don't know where and how to start.
Upvotes: 1
Views: 7803
Reputation: 31
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>
Upvotes: 3
Reputation: 14
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.
Upvotes: -1
Reputation: 591
This is better handled in the HomePage
component 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>
)
}
}
Upvotes: 0