Reputation: 15237
I have a ReactJS that is expecting a list of artist objects. I read the ReactJS docs, and found this:
So I thought, Ok, I'll fire off my fetchArtists()
action (I'm using Redux) from within the componentDidMoun()
method.
I am doing that, but for some reason it isn't working. The list of artists I'm getting back is undefined
even thought in the logger, I can see that the artists were returned.
CODE
Here's the app container component.
class App extends Component {
componentDidMount() {
this.props.dispatch(ArtistsListActions.fetchArtists());
}
render() {
return (
<div className="App">
<Header />
<Route exact path="/" render={routeProps => <ArtistList {...routeProps} artists={this.props.artists} />} />
<Route exact path="/artist/:artistUrlName" component={Artist} />
</div>
);
}
}
ArtistList.propTypes = {
artists: PropTypes.array.isRequired
};
const mapStateToProps = function(state) {
console.log('The state is:');
console.log(state);
}
export default connect(mapStateToProps)(App);
The console.log(state);
within the mapStateToProps()
method should show me a state with artists loaded, but I don't, artists
is an empty array at that point.
UPDATE
I did what you all suggested about returning an option in my mapStateToProps()
method, but that still doesn't work. I've captured what is happening in this screencast.
Upvotes: 1
Views: 671
Reputation: 2975
The error is being thrown before your axios call. The initial state does not match the shape of the response from your api.
You can either try and normalise this through your actionCreators or update your inital state to match the API:
const initialState = {
isFetching: false,
fetchComplete: false,
artists: {artists: {verified:[]}},
error: null
};
For completeness, this is the mapStateToProps you would need if you change your initial state:
const mapStateToProps = function(state) {
console.log(state);
return {
artists: state.artists.artists.verified
}
}
Upvotes: 1
Reputation: 1233
This fails due to Redux do not get expected result from mapStateToProps method, which should return Object to be merged to Component props. It is treat as developer's failure therefore Redux breaks the loop and do not process events anymore, forcing dev to fix it.
Also there is shortcut for this.props.dispatch(ArtistsListActions.fetchArtists())
, if you pass function as a second parameter to connect it will automatically wrap it within dispatch and make wrapped function available under props:
class App extends Component {
componentDidMount() {
this.props.fetchArtists();
}
render() {
return (
<div className="App">
<Header />
<Route exact path="/" render={routeProps => <ArtistList {...routeProps} artists={this.props.artists} />} />
<Route exact path="/artist/:artistUrlName" component={Artist} />
</div>
);
}
}
ArtistList.propTypes = {
artists: PropTypes.array.isRequired
};
const mapStateToProps = function(state) {
console.log('The state is:');
console.log(state);
const artists = state.artists.artists && state.artists.artists.verified;
return {artists: artists || []};
}
const mapDispatchToProps = {
fetchArtists: ArtistsListActions.fetchArtists;
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
Upvotes: 2
Reputation: 493
So, you probably forgot dispatch to props...
class App extends Component {
componentDidMount() {
this.props.fetch(); //Call just your mapped dispatch
}
render() {
return (
<div className="App">
<Header />
<Route exact path="/" render={routeProps => <ArtistList {...routeProps} artists={this.props.artists} />} />
<Route exact path="/artist/:artistUrlName" component={Artist} />
</div>
);
}
}
ArtistList.propTypes = {
artists: PropTypes.array.isRequired
};
const mapStateToProps = function(state) {
console.log('The state is:');
console.log(state);
}
const mapDispatchToProps = (dispatch) => {
return {
fetch: () => dispatch(ArtistsListActions.fetchArtists())
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App); //Pass new method here
Upvotes: 0