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]
?
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.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.