So I may overthinking this issue, but I can't seem to make my component work asynchronously.
Essentially I am using thunk to dispatch an action that will retrieve a JSON from a local server and once it receives, pass it down to the reducer and update the state, thus then rendering the component.
Instead, the component receives the app's intitial state as {} empty object, thus giving an error when I am using map to render the component.
Here's what I have:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import thunk from 'redux-thunk';
import promise from 'redux-promise';
import App from './components/app';
import VotesContainer from './containers/votes-container';
import NewPoll from './containers/newpoll';
import VoteTemplate from './components/vote-template';
import Login from './components/auth/login';
import Signup from './components/auth/signup';
import reducers from './reducers/';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducers, composeEnhancers(applyMiddleware(thunk)))
ReactDOM.render(
<Provider store={store}>
<Router history={browserHistory}>
<Route path="/" component={App}>
<IndexRoute component={VoteTemplate} />
<Route path="allposts" component={VotesContainer} />
<Route path="login" component={Login} />
<Route path="signup" component={Signup} />
<Route path="newpoll" component={NewPoll} />
</Route>
</Router>
</Provider>
, document.querySelector('#project'));
actions/index.js
import axios from 'axios';
const ROOT_URL = 'http://localhost:1234';
import { browserHistory } from 'react-router';
import { FETCH_VOTES, CAST_VOTE } from './types';
export function fetchVotes(){
return function(dispatch){
axios.get(`${ROOT_URL}/newpost`)
.then(response => {
console.log('Dispatch!!')
dispatch({
type: FETCH_VOTES,
payload: response.data
})
})
}
}
container
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions'
class VotesContainer extends Component {
componentDidMount(){
this.props.fetchVotes()
}
renderCards(){
return(
<div className="col s12 m6 l4">
<div className="card blue-grey darken-1">
<div className="card-content white-text">
<span className="card-title">Vote App Title #1</span>
<p className="description">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</div>
<div className="card-action">
<a href="#">Results</a>
<a href="#">Date Created</a>
</div>
</div>
</div>
)
}
render(){
console.log(this.props.voteData)
return(
<main className="votes-container container">
<div className="row">
{this.props.voteData.map(this.props.voteData.vote)} <<======= gives error since it is null first before dispatch
</div>
</main>
)
}
}
function mapStateToProps(state){
return {voteData: state.voteData};
}
export default connect(mapStateToProps, actions)(VotesContainer)
this.props.voteData.vote(this.props.voteData.vote || []).map(this.renderCards)will do what you want. You will start from the initial state which is an empty object then when you dispatch it will be populated unless you want to start with another initial state from server?redux-thunkisn't working correctly