Reputation: 8936
My codes:
render() {
console.log( 'render, state' + Array.isArray(this.props.users) + ',' + JSON.stringify(this.props.users) );
return (
<section>
<div>testing</div>
<div>{JSON.stringify(this.props.users)}</div>
<ul>
{this.props.users.map( user => <li>{user.email}</li>)}
</ul>
</section>
);
}
Both <div>testing</div>
and <div>{JSON.stringify(this.props.users)}</div>
work fine (after removing <ul>...</ul>
). But <ul>...</ul>
did not work. the error is:
Uncaught TypeError: Cannot read property 'map' of undefined
Any comments welcomed. Thanks
UPDATE
The following codes work fine, this.props.users
is an Array, and all the console logs look OK. I just need to know why <ul>{this.props.users.map( user => <li>{user.email}</li>)}</ul>
not work. Why this.props.users
in <ul>...</ul>
is undefined.
render() {
console.log( 'render, state' + Array.isArray(this.props.users) + ',' + JSON.stringify(this.props.users) );
return (
<section>
<div>testing</div>
<div>{JSON.stringify(this.props.users)}</div>
</section>
);
}
the console output of the above codes (only two s):
render, statetrue,[{"_id":"5831e6df511e","updatedAt":"removed","createdAt":"removed","email":"removed","password":"xxxx","__v":0,"role":"xxx","profile":{"firstName":"test","lastName":"tester"}},{...}, {...}]
UPDATE
My codes:
import { connect } from 'react-redux';
import { fetchAllUsers } from '../../actions/index';
class HomePage extends Component {
componentWillMount() {
console.log( 'componentWillMount()' );
this.props.fetchAllUsers();
}
render() {
console.log( 'render(), ' + Array.isArray(this.props.users) + ',' + JSON.stringify(this.props.users) );
return (
<section>
<div>{JSON.stringify(this.props.users)}</div>
</section>
);
}
}
function mapStateToProps(state) {
console.log( 'state:' + JSON.stringify(state) );// working fine, and the console.log is OK. not added to this post
return {
users: state.admin.users
}
}
export default connect(mapStateToProps, {fetchAllUsers})(HomePage);
console.log (some details in the User objects removed.):
render(), true,[{"_id":"5831","profile":{"firstName":"test","lastName":"tester"}},{"_id":"5831e874cedf511f", "profile":{"firstName":"cccc","lastName":"cc"}},{"_id":"5831120","profile":{"firstName":"cccccccc","lastName":"ccc"}}]
And, on the webpage, the string of this.props.users
is shown.
My question is why <ul>{this.props.users.map( user => <li>{user.email}</li>)}</ul>
not work, but <div>{JSON.stringify(this.props.users)}</div>
working fine.
I think I already described my questions clearly. If more information needed, please tell me.
More details
my admin_reducer.js
import { FETCH_ALL_USERS } from '../actions/types';
const INITIAL_STATE = { users:[] };
export default function (state = INITIAL_STATE, action) {
console.log( 'users is action.payload:'+JSON.stringify( { users:action.payload } ) );
return Object.assign( {}, state, {users:action.payload});
//return { ...state, users:action.payload };
}
my index.js
import adminReducer from './admin_reducer';
const rootReducer = combineReducers({
...
admin: adminReducer
});
export default rootReducer;
my action.js
export function fetchAllUsers() {
return function(dispatch) {
axios.get(`${API_URL}/user/all`)
.then(response => {
dispatch({
type: FETCH_ALL_USERS,
payload: response.data
});
})
.catch(response => dispatch(errorHandler(response.data.error)))
}
}
UPDATE
why console log of console.log(this.props.users)
is [object Object],[object Object],[object Object]
?
Upvotes: 0
Views: 2330
Reputation: 5927
You can call this without error..
JSON.stringify(this.props.users)
...because it just outputs "undefined"). That is valid. However, if you try to call a method on the undefined that was returned, of course that fails...
// Following tries to call undefined.map(), which is of course wrong
this.props.users.map( user => <li>{user.email}</li>)
Common shorthand to address your scenario uses a "short-circuit operator" (like a quickie "if (is true)")...
<ul>{this.props.user && this.props.users.map( user => <li>{user.email}</li>)}</ul>
^^ Note the "this.props.user && ", which prevents the following this.props.user.map() from being called if this.props.user is null or undefined
Upvotes: 0
Reputation: 454
First of, according to react docs, async requests should be made inside the componentDidMount
method.
Secondly, to make sure that you're not trying to map
an un-initialized array, use this:
<ul>{(this.props.users || []).map( user => <li>{user.someProperty}</li> )}</ul>
This should cover it in case you forgot to initialize the array for some reason.
Upvotes: 1