0

I am new in react, and try to make my first project using such features: react, redux, react-router, redux-thunk. I am fetching data from url with json. It works fine on powerfull pc, on wicker it will not work becouse as i understud, it is starts to fetch then it try to render components without data and only then it gets data from url... Also same result i have when i refresh innerpage, it will try to render components before it get data.

So here is creating of store:

const middleware = [routerMiddleware(hashHistory)];

const store = createStore( combineReducers({
    reducers:reducers,
    routing:routerReducer
}),compose(applyMiddleware(...middleware, thunk), 
          window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()));

const history = syncHistoryWithStore(hashHistory, store);

Then here is my provider:

ReactDOM.render(
    <Provider store={store}>
    <Router history={history}>     
      <Route path="/" component={withTransition(App)}>
        <IndexRoute component={Projects} />
        <Route path="project/:id/" component={SingleProject}>
        </Route>
      </Route>
    </Router>
    </ Provider>,
    document.getElementsByClassName('root')[0]
)

I am fetching data in that way:

function fetchProjRequest(){
  return {
    type: "FETCH_PROJ_REQUEST"
  }
}

function fetchProjSuccess(payload) {
  return {
    type: "FETCH_PROJ_SUCCESS",
    payload
  } 
}

function fetchProjError() {
  return {
    type: "FETCH_PROJ_ERROR"
  }
}

function fetchProj() {
  const URL = "http://****.com/data/proj";
  return fetch(URL, { method: 'GET'})
     .then( response => Promise.all([response, response.json()]));
}

class App extends Component{

  constructor(props){
    super(props);
    this.props.fetchProjWithRedux();

  }


  render(){
    return (
     <div className={styles.app}>
       <Logo />
        <TagFilter />
        <div className={styles.content}>
          {this.props.children}
        </div>
      </div>
    )
  }
}

function mapStateToProps(state){
  return {
    proj: state.proj
  }
}

export default connect(
  state => ({
    proj: state.reducers.projects.proj
  }),
  dispatch =>({
    fetchProjWithRedux: () => {
      fetchProj().then(([response, json]) =>{
        if(response.status === 200){
          dispatch(fetchProjSuccess(json))
        }
        else{
          dispatch(fetchProjError())
        }
      })
    },
  })
)(App);

It would be greate if someone of you tell me were i was wrong :( It is very imortant for me!

Ivan Kaduk
  • 60
  • 1
  • 7
  • 1
    it supposed to work like that, since fetching is asynchronous. Introduce a isLoading boolean which changes to false when you get the response. When its true render a loader or something instead of the actual body of the component – Johnny Klironomos Mar 12 '17 at 02:33
  • @JohnnyKlironomos have you see some live example of that, it would be greate to look an this on real? – Ivan Kaduk Mar 12 '17 at 18:14
  • You may also want to look into an async middleware for redux, such as [redux-thunk](https://github.com/gaearon/redux-thunk). – Michael Peyper Mar 13 '17 at 11:51
  • @MichaelPeyper Thank you, but i have already using it, but it is not helping... – Ivan Kaduk Mar 13 '17 at 19:18

1 Answers1

1

Here is a gist of a hoc that takes care of what you need.

Make sure to introduce a isDataLoaded boolean prop in your reducer and make it true when FETCH_PROJ_SUCCESS is called. Hope it helps.

Some changes to your code:

import dataLoader from './dataLoader';

const AppWithLoader = dataLoader(App);

export default connect(
  state => ({
    isDataLoaded: state.proj.isDataLoaded,
    proj: state.reducers.projects.proj
  }),
  dispatch =>({
    dispatchGetData: () => {
      fetchProj().then(([response, json]) =>{
        if(response.status === 200){
          dispatch(fetchProjSuccess(json))
        }
        else{
          dispatch(fetchProjError())
        }
      })
    },
  })
)(AppWithLoader);
  • Hmm, interesting module. Didn`t know that such exist. For now I have found solution, but in future, i think i will use it! Thank you! – Ivan Kaduk Mar 22 '17 at 18:06