Comments (11)
Can I see the code for the dispatched action? I wrap mine in a promise instead of the redux thunk promise
from react-router-fetch.
also, componentWillMount
should be used for this if it is a single page app and doesn't have server loaded data to begin with.
from react-router-fetch.
notice I wrap it in my own promise. I ran into this issue as well right away as well with thunk
from react-router-fetch.
my trimmed down app.js from a redux-thunk based app:
// @flow
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { Helmet } from 'react-helmet'
import { withRouter } from 'react-router'
import { renderRoutes } from 'react-router-config'
import type { Match, RouterHistory, Location } from 'react-router-dom'
import NProgress from 'nprogress'
import reactRouterFetch from 'react-router-fetch'
NProgress.configure({ showSpinner: false })
class App extends Component<PropsT, StateT> {
constructor(props) {
super(props)
this.state = {
isAppFetching: false,
appFetchingError: null
}
}
componentWillMount() {
this.fetchRoutes(this.props)
}
componentWillReceiveProps(nextProps) {
// see if the route has changed
const current = this.props.location.pathname
const next = nextProps.location.pathname
if (current === next) {
return
}
this.fetchRoutes(nextProps)
}
shouldComponentUpdate(nextProps, nextState) {
// same check is needed here to that there is not a flash of rendering
return !nextState.isAppFetching
}
fetchRoutes(props) {
const { dispatch, location } = props
// to get the tests to pass :(
if (document) NProgress.start()
this.setState({
isAppFetching: true,
appFetchingError: null
})
Promise.all([
reactRouterFetch(routeConfig, location, { dispatch })
])
.then(() => {
this.setState({
isAppFetching: false,
appFetchingError: null
})
if (document) NProgress.done()
})
.catch(err => {
this.setState({
isAppFetching: false,
appFetchingError: err
})
if (document) NProgress.done()
})
}
renderAppRoutes() {
const { route } = this.props
const { isAppFetching, appFetchingError } = this.state
if (!isAppFetching && appFetchingError) {
if (process.env.NODE_ENV !== 'production') console.log(appFetchingError)
if (process.env.NODE_ENV === 'production') {
window.Rollbar.error(
`Error occured in App Component/Bubbled up to App`,
appFetchingError
)
}
return (
<ErrorPage
/>
)
}
if (isAppFetching) {
return (
<p>Loading...</p>
)
}
return renderRoutes(route.routes)
}
render() {
return (
<section className="App expanded row">
<section className="App__content">
{this.renderAppRoutes()}
</section>
</section>
)
}
}
const mapStateToProps = (state, ownProps) => {
return {
stuff: state.stuff
}
}
const connectedApp = connect(mapStateToProps)(App)
export default withRouter(connectedApp)
and a sample route:
export class SampleRoute extends Component<PropsT, StateT> {
static fetch(match, location, { dispatch }) {
return dispatch(myStuff.actions.fetchMyStuff())
}
render () {
const {
myStuff
} = this.props
return (
<main className="">
{myStuff.title}
</main>
)
}
}
const mapStateToProps = (state, ownProps) => {
return {
myStuff: state.myStuff
}
}
export default connect(mapStateToProps)(SampleRoute)
and a sample thunk:
export function fetchThingLoading(): ActionT {
return {
type: FETCH_THING_LOADING
}
}
export function fetchThingSuccess(
response: Thing | string
): ActionT {
return {
type: FETCH_THING_SUCCESS,
payload: response
}
}
export function fetchThingError(err: ErrorT): ActionT {
return {
type: FETCH_THING_ERROR,
error: true,
payload: err
}
}
export function fetchThing(): Function {
return (dispatch: Function, getState: Function) => {
dispatch(fetchThingLoading())
return new Promise((resolve: Function, reject: Function) => {
fetch(`/api/thing`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
credentials: 'same-origin'
})
.then(handleResponse)
.then(handleData(resolve, dispatch, fetchThingSuccess))
.catch(handleError(reject, dispatch, fetchThingError))
})
}
}
I hope this helps!
from react-router-fetch.
Sure, this is my action code:
import { showLoading, hideLoading } from 'react-redux-loading-bar';
import { restLeagueCountriesSlug } from '../api/leagueCountries';
import {omit} from 'lodash';
import {INVALIDATE_LEAGUE_COUNTRIES,REQUEST_LEAGUE_COUNTRIES,RECIEVE_LEAGUE_COUNTRIES} from './constants';
export const invalidate = (type, payload = {}) => ({type, payload});
export const request = (type, payload = {}) => ({type, payload});
export const receive = (type, payload = {}) => ({type, payload});
export const fetchItems = param => dispatch => {
dispatch(showLoading());
dispatch(request(REQUEST_LEAGUE_COUNTRIES, {param}));
return restLeagueCountriesSlug(param).then(res => {
const {items = []} = res.data ? res.data : {};
dispatch(receive(RECIEVE_LEAGUE_COUNTRIES, {items, param, ...omit(res.data, ['items'])}));
dispatch(hideLoading());
}).catch(error => {
dispatch(invalidate(INVALIDATE_LEAGUE_COUNTRIES, {param}));
dispatch(hideLoading());
console.error(error);
});
};
export const shouldFetch = (state, key, param) => {
const item = state[key][param]
? state[key][param]
: false;
return !item ?
true :
item.isFetching ?
false :
item.didInvalidate;
};
export const fetchLeagueCountriesIfNeeded = (key = 'leagueCountries', param = 'all') => (dispatch, getState) => {
if (shouldFetch(getState(), key, param)) {
return dispatch(fetchItems(param));
}
};
from react-router-fetch.
I did try removing the componentWillMount but had the same issues.
from react-router-fetch.
I mean to replace componentDidMount with componentWillMount for fetching at least
from react-router-fetch.
export function fetchThing() {
return (dispatch, getState) => {
dispatch(fetchThingLoading())
return new Promise((resolve, reject) => {
fetch(`/users/`, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
credentials: 'same-origin'
})
.then(handleResponse)
.then(handleData(resolve, dispatch, fetchFavoritesSuccess))
.catch(handleError(reject, dispatch, fetchFavoritesError))
})
}
}
from react-router-fetch.
I tried running the below from your code but still the same issues. When i look at my logger it always seems like it is detecting the promise correctly: http://prntscr.com/i8bo62 It just renders the component before its fetching is false.
export function fetchThing(param = 'all') {
return (dispatch, getState) => {
dispatch(request(REQUEST_LEAGUE_COUNTRIES, {param}));
return new Promise((resolve, reject) => {
restLeagueCountriesSlug('all')
.then(res => {
const {items = []} = res.data ? res.data : {};
dispatch(receive(RECIEVE_LEAGUE_COUNTRIES, {items, param, ...omit(res.data, ['items'])}));
resolve(res);
});
});
};
}
from react-router-fetch.
Thank you, I stripped everything down and got it working with your code and even with my original actions, so there must be an issue elsewhere. I am thinking maybe Material-UI HOC's
I will add things back one by one and post my findings in case anyone else has issues.
I really appreciate your help.
from react-router-fetch.
Managed to fix this. I had a bindactioncreateors in a wrapper HOC for each component which seemed to cause problems. I removed the connect from the HOC and added it directly to the App component and passed dispatch back.
Thanks again for all your help.
This was the fix:
const mapDispatchToProps = dispatch => {
const boundActionCreators = bindActionCreators({
toggleDrawer,
showDrawer,
hideDrawer,
hideAllDrawers,
logoutUser
}, dispatch);
const allActionProps = {...boundActionCreators, dispatch};
return allActionProps;
};
const connectedApp = connect(mapStateToProps,mapDispatchToProps)(App);
from react-router-fetch.
Related Issues (6)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-router-fetch.