Reputation: 1539
I'm following the reactjs
tutorial, and I keep running into an issue when
passing the value from the state of one component into another component.
The error Cannot read property 'map' of undefined'
is thrown when the map
function in the CommentList
component is executed.
What would cause the
prop
to beundefined
when passing fromCommentBox
into theCommentList
?
// First component
var CommentList = React.createClass({
render: function() {
var commentNodes = this.props.data.map(function (comment){
return <div><h1>{comment.author}</h1></div>;
});
return <div className="commentList">{commentNodes}</div>;
}
});
// Second component
var CommentBox = React.createClass({
getInitialState: function(){
return {data: []};
},
getComments: function(){
$.ajax({
url: this.props.url,
dataType: 'json',
success: function(data){ this.setState({data: data}) }.bind(this),
error: function(xhr, status, err){ console.error(url, status, err.toString()) }.bind(this)
});
},
componentWillMount: function(){
this.getComments()
},
render: function(){
return <div className="commentBox">{<CommentList data={this.state.data.comments}/>}</div>;
}
});
React.renderComponent( <CommentBox url="comments.json" />, document.getElementById('content'));
Upvotes: 99
Views: 556657
Reputation: 135
In my case it happens when I try to add types to Promise.all
handler:
Promise.all([1,2]).then(([num1, num2]: [number, number])=> console.log('res', num1));
If I remove : [number, number]
, the error is gone.
Upvotes: 0
Reputation: 87
In my case I solved this error by adding "?" condition.
<div className="hotelContainer__img">
{photos.map((item, index) => (
<img
src={item}
alt=""
key={index}
onClick={() => handleOpen(index)}
/>
))}
</div>
<div className="hotelContainer__img">
{photos?.map((item, index) => (
<img
src={item}
alt=""
key={index}
onClick={() => handleOpen(index)}
/>
))}
</div>
Upvotes: 0
Reputation: 1
react js when api call data app: [{programname: "string", status: "duplicate"}]
Upvotes: 0
Reputation: 532
Here is what my issue where:
{props.users.map((item,index)=>(
<div className="items" key={index}>
<div className="text-center">
<p className="fs-12">{item}</p>
</div>
</div>
))}
And then i just fixed the issue with adding this code. It works just as if and else statement.
{ props.users ? props.users.map((item,index)=>(
<div className="items" key={index}>
<div className="text-center">
<p className="fs-12">{item}</p>
</div>
</div>
)) : <p>Users is empty</p>}
Upvotes: 4
Reputation: 11
This worked for me. if i use props.worktyp.map it throws me an error of map is not defined.
//App.js
const worktyp = [
"Full-time",
"casual",
"part-time",
"contract"
];
function Main(props){
return(
<section>
<p>This the main body</p>
<ul style = {{textAlign:"left"}}>
**{worktyp.map((work) => <li>{work}</li>)}**
</ul>
</section>
);
}
function App() {
return (
<div className="App">
<Header name="initial"/>
**<Main work={worktyp}/>**
<Foot year ={new Date().getFullYear()}/>
</div>
);
}
//index.js
ReactDOM.render(
<App />,
document.getElementById('root')
);
Upvotes: 0
Reputation: 2695
The error occur mainly becuase the array isnt found. Just check if you have mapped to the correct array. Check the array name or declaration.
Upvotes: 2
Reputation: 2502
I considered giving a comment under the answer by taggon to this very question, but well, i felt it owed more explanation for those interested in details.
Uncaught TypeError: Cannot read property 'value' of undefined is strictly a JavaScript error.
(Note that value can be anything, but for this question value is 'map')
It's critical to understand that point, just so you avoid endless debugging cycles.
This error is common especially if just starting out in JavaScript (and it's libraries/frameworks).
For React
, this has a lot to do with understanding the component lifecycle methods.
// Follow this example to get the context
// Ignore any complexity, focus on how 'props' are passed down to children
import React, { useEffect } from 'react'
// Main component
const ShowList = () => {
// Similar to componentDidMount and componentDidUpdate
useEffect(() => {// dispatch call to fetch items, populate the redux-store})
return <div><MyItems items={movies} /></div>
}
// other component
const MyItems = props =>
<ul>
{props.items.map((item, i) => <li key={i}>item</li>)}
</ul>
/**
The above code should work fine, except for one problem.
When compiling <ShowList/>,
React-DOM renders <MyItems> before useEffect (or componentDid...) is called.
And since `items={movies}`, 'props.items' is 'undefined' at that point.
Thus the error message 'Cannot read property map of undefined'
*/
As a way to tackle this problem, @taggon gave a solution (see first anwser or link).
Solution: Set an initial/default value.
In our example, we can avoiditems
being 'undefined' by declaring adefault
value of an empty array.
Why? This allows React-DOM to render an empty list initially.
And when theuseEffect
orcomponentDid...
method is executed, the component is re-rendered with a populated list of items.
// Let's update our 'other' component
// destructure the `items` and initialize it as an array
const MyItems = ({items = []}) =>
<ul>
{items.map((item, i) => <li key={i}>item</li>)}
</ul>
Upvotes: 6
Reputation: 179
The error "Cannot read property 'map' of undefined"
will be encountered if there is an error in the "this.props.data"
or there is no props.data array.
Better put condition to check the the array like
if(this.props.data){
this.props.data.map(........)
.....
}
Upvotes: 7
Reputation: 111
You need to put the data before render
Should be like this:
var data = [
{author: "Pete Hunt", text: "This is one comment"},
{author: "Jordan Walke", text: "This is *another* comment"}
];
React.render(
<CommentBox data={data}/>,
document.getElementById('content')
);
Instead of this:
React.render(
<CommentBox data={data}/>,
document.getElementById('content')
);
var data = [
{author: "Pete Hunt", text: "This is one comment"},
{author: "Jordan Walke", text: "This is *another* comment"}
];
Upvotes: 11
Reputation: 571
I think you forgot to change
data={this.props.data}
to
data={this.state.data}
in the render function of CommentBox. I did the same mistake when I was following the tutorial. Thus the whole render function should look like
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm />
</div>
);
}
instead of
render: function() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.props.data} />
<CommentForm />
</div>
);
Upvotes: 14
Reputation: 1936
First of all, set more safe initial data:
getInitialState : function() {
return {data: {comments:[]}};
},
And ensure your ajax data.
It should work if you follow above two instructions like Demo.
Updated: you can just wrap the .map block with conditional statement.
if (this.props.data) {
var commentNodes = this.props.data.map(function (comment){
return (
<div>
<h1>{comment.author}</h1>
</div>
);
});
}
Upvotes: 70