Giter Site home page Giter Site logo

Comments (11)

kellyrmilligan avatar kellyrmilligan commented on May 29, 2024 1

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.

kellyrmilligan avatar kellyrmilligan commented on May 29, 2024 1

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.

kellyrmilligan avatar kellyrmilligan commented on May 29, 2024 1

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.

kellyrmilligan avatar kellyrmilligan commented on May 29, 2024 1

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.

webbygregg avatar webbygregg commented on May 29, 2024

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.

webbygregg avatar webbygregg commented on May 29, 2024

I did try removing the componentWillMount but had the same issues.

from react-router-fetch.

kellyrmilligan avatar kellyrmilligan commented on May 29, 2024

I mean to replace componentDidMount with componentWillMount for fetching at least

from react-router-fetch.

kellyrmilligan avatar kellyrmilligan commented on May 29, 2024
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.

webbygregg avatar webbygregg commented on May 29, 2024

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.

webbygregg avatar webbygregg commented on May 29, 2024

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.

webbygregg avatar webbygregg commented on May 29, 2024

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 photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.