Reputation: 1904
I have a default state as shown below, I'm fetching the data from postgres, considering a situation where my photos array is null, the state does not get updated.
The reason is I'm accessing some of the parameters directly, {this.state.media.photos[this.state.media.selectedMediaIndex].url}
What I see from actions is
action Object {type: "FETCH_MEDIA_FULFILLED", payload: Array[1]}
error TypeError: Cannot read property 'undefined' of null
action Object {type: "FETCH_MEDIA_REJECTED", payload: TypeError: Cannot read property 'undefined' of null at Media.render (http://localhost:3000/clien…}
What is the right way of doing this? While setting state should I create a default object, update all parameters and then set the state?
There is no issues if there is at least 1 array element of photos, the only problem is at the first state when the photos column is null.
State :
this.state = {
media : {
video : "",
photos : [{
title : "",
url : "",
category : {
interior : false,
exterior : true,
closeup : false
},
display : {
preview : false,
featured : true,
none : false
},
size : "",
attribution_link : "",
attribution_text : "",
description : ""
}],
selectedMediaIndex : 0
}
}
Once the componentWillReceiveProps receives the nextProps, I'm updating my state.
componentWillReceiveProps(nextProps){
if(nextProps.media.length){
this.setState({
media : nextProps.media[0]
})
}
}
CONNECTOR :
const mapStateToProps = function (store) {
return {
media: store.media.media
};
};
const PhotoConnector = Redux.connect(mapStateToProps)(Media);
export default class MediaConnector extends React.Component {
render() {
return (
<PhotoConnector media={this.props.media}/>
);
}
}
REDUCER :
export default function reducer(
state={
media: [],
fetching: false,
fetched: false,
error: null,
}, action) {
switch (action.type) {
case "FETCH_MEDIA": {
return {...state, fetching: true}
}
case "FETCH_MEDIA_REJECTED": {
return {...state, fetching: false, error: action.payload}
}
case "FETCH_MEDIA_FULFILLED": {
return {
...state,
fetching: false,
fetched: true,
media: action.payload,
}
}
}
return state
}
UPDATE
I got a way not to get the error, I'm basically checking if the photos is null and setting a default state array to it.
componentWillReceiveProps(nextProps){
if(nextProps.media.length){
if(!nextProps.media.photos){
this.setState({
media : {
video : nextProps.media[0].video,
photos : [{
title : "",
url : "",
category : {
interior : false,
exterior : true,
closeup : false
},
display : {
preview : false,
featured : true,
none : false
},
size : "",
attribution_link : "",
attribution_text : "",
description : ""
}],
selectedMediaIndex : 0
}
})
}
else{
this.setState({
media : nextProps.media[0]
})
}
}
}
Any other solution will be appreciated.
Upvotes: 1
Views: 198
Reputation: 5408
Why to not just have default props?
PhotoConnector.defaultProps = {
media: {
video: [],
photos: [],
}
};
Or maybe default store?
class Media {
constructor(js = {}) {
this.video = js.video || [];
this.photos = js.photos || [];
}
}
state={
media: [new Media()],
}
case "FETCH_MEDIA_FULFILLED": {
return {
...state,
fetching: false,
fetched: true,
media: action.payload.map(m => new Media(m)),
}
Upvotes: 3