Reputation: 4481
Im trying to display some data using map function but im keep on getting warnings and errors. they are
Warning: There is an internal error in the React performance measurement code. Did not expect componentDidMount timer to start while render timer is still in progress for another instance.
and the other one is
Uncaught TypeError: Cannot read property 'map' of undefined
i found out that this.props.courses.map returns null but i still cant figure out why?
import React,{PropTypes} from 'react';
import {connect} from 'react-redux';
import * as courseActions from '../actions/courseActions';
class CoursesPage extends React.Component{
constructor(props,context){
super(props,context);
this.state={
course:[{id:1,title:'hello'}]
};
this.onTitleChange = this.onTitleChange.bind(this);
this.onClickSave = this.onClickSave.bind(this);
}
onTitleChange(event){
const course = this.state.course;
course.title = event.target.value;
this.setState({course:course});
}
onClickSave(){
this.props.dispatch(courseActions.createCourse(this.state.course));
}
courseRow(){
return this.props.courses.map((course)=>{
return(
<div key={course.id}>{course.title}</div>
);
});
}
render(){
return(
<div>
<h2>hello</h2>
<h3>{this.courseRow()}</h3>
<input type="text" onChange={this.onTitleChange} value={this.state.course.title}/>
<input type="submit" value="save" onClick={this.onClickSave}/>
</div>
);
}
}
CoursesPage.propTypes ={
dispatch: PropTypes.func.isRequired,
courses: PropTypes.array.isRequired
};
function mapStateToProps(state,ownProps){
return{
courses:state.courses
};
}
export default connect(mapStateToProps)(CoursesPage);
here is my reducer
export default function courseReducer(state = [],action){
switch(action.type){
case 'CREATE_USER':
state.push(action.user);
return [...state,Object.assign({},action.user)];
default:
return state;
}
}
my rootReducer
import {combineReducers} from 'redux';
import users from './userReducer';
import courses from './courseReducer';
const rootReducer = combineReducers({
users:users,
courses:courses
});
export default rootReducer;
the store
import {createStore,applyMiddleware} from 'redux';
import rootReducer from '../reducers/rootReducer';
export default function configureStore(initialState){
return createStore(
rootReducer,
initialState
);
}
Upvotes: 1
Views: 5555
Reputation: 4481
After modifying the code with the help of both @Harkirat Saluja and @Yang Shun. i manages to fix the issue which was initializing courses so i changed my Reducer as below
state = [] did the trick!
export default function courseReducer(state = [],action){
switch (action.type) {
case 'CREATE_COURSE':
return [...state,Object.assign({},action.course)];
default:
return state;
}
}
Upvotes: 3
Reputation: 8114
In your reducer where are you updating courses?? I can only see users from the code you posted.
const initialState = {
courses : [],
}
export default function courseReducer(state =initialState,action){
switch(action.type){
//create a course or update it , else value is
//undefined and your map would throw error.
case 'CREATE_COURSES':
return Object.assign({},state,{
courses : action.user}
);
default:
return state;
}
}
Also in your render method you need to check if this value is filled then only run map.
<h3>{this.props.courses.length > 1 ? this.courseRow() : null}</h3>
Upvotes: 3
Reputation: 53169
Your Redux store's courses
might be undefined
at the start and hence this.props.courses
becomes undefined
. Trying to access .map
of undefined
will give you the error you mentioned above. There are a few ways to fix this:
Approach 1 (Recommended): Set the initial value of the state.courses
to empty array []
in your the reducer. Refer to the documentation on Reducers to see how to set an initial state: http://redux.js.org/docs/basics/Reducers.html.
Approach 2: Set a default value for props.courses
in mapStateToProps
.
function mapStateToProps(state,ownProps){
return {
courses: state.courses || []
};
}
Approach 3: Check that this.props.courses
is not undefined
or null
before rendering it:
courseRow() {
if (!this.props.courses) {
return null;
}
return this.props.courses.map((course)=>{
return(
<div key={course.id}>{course.title}</div>
);
});
}
Upvotes: 5
Reputation: 566
Your mapStateToProps
is returning a reducer instead of actual props
that you can use right away. It should probably look like this:
function mapStateToProps(state,ownProps){
return{
...state.courses
};
}
Upvotes: 2