Cannot read property 'map' of undefined on react.js - reactjs

Hello I'm a beginner of react, I'm stuck Cannot read the property 'map' of undefined, I understand is a type error please help me.
import React, { Component } from 'react';
import Message from "./Message";
class MessageList extends Component {
render() {
const { messages } = this.props;
return messages.map(message => (
<ul>
<Message message={message} />
</ul>
));
}
}
export default MessageList;

To u can try to use the "null object” pattern to avoid such errors when the prop is not uet to be sent to the component, the issue is not coming from the code you showed us so we cant help you find the main problem
Null object pattern Inside of the render method (also in this case is a default param):
const { messages = [] } = this.props;

As suggested messages can be null in which case map will throw an error.
However, you also haven't constructed props which means messages will always be null.
import React, { Component } from 'react';
import Message from "./Message";
class MessageList extends Component {
constructor(props) {
super(props);
// state if you need it.
this.state = { counter: 0 };
}
render() {
const { messages } = this.props;
return messages && messages.map(message => (
<ul>
<Message message={message} />
</ul>
));
}
}
export default MessageList;
Tested and this works.

Related

how to get rid of TypeError: Cannot read property 'map' of undefined error?

I am trying to get id, first and last name of users using createListItems() inside user-list.js file.
But, I got
"TypeError: Cannot read property 'map' of undefined"
error when I ran the program, and (line7 / user-list.js) return this.props.users.map(user => { is red (not working).
I do not know why I get this error, and how to fix it.
Does anyone know how to get rid of this error?
user-list.js
import React, { Component } from "react";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
class UserList extends Component {
createListItems() {
return this.props.users.map(user => {
return (
<li key={user.id}>
{user.first}
{user.last}
</li>
);
});
}
render() {
return <ul>{this.createListItems()}</ul>;
}
}
function mapStateToProps(state) {
return {
users: state.users
};
}
export default connect(mapStateToProps)(UserList);
index.js
import React, { Component } from "react";
import UserList from "../containers/user-list";
class Index extends Component {
state = {};
render() {
return (
<div>
<h2>username list:</h2>
<UserList />
<hr />
<h2>user details:</h2>
</div>
);
}
}
export default Index;
As warkentien2 mentioned, you're not passing the users array to the <UserList /> component. You need to create an array in index.js of your users (manually or pulled from somewhere else) and pass it off like this: <UserList users={[{id: 1, first: "John", last: "Doe"}]} />
When UserList mounts, it takes initial state. And initially users state might be null / empty.
You need to check if data is present,
<ul>{ this.props.users && this.props.users.length > 0 && this.createListItems() }</ul>;

React Context not passing data to its child components

I am a beginner in React. Looking at a few medium articles and React docs(which is complicated) I have tried to implement this very basic Context API.
I have missed some basic point which is the reason why I haven't got the correct result which is to pass data through the components tree and access them in the child component.
Please let me know how to correct given code snippet and what have I missed.
import React from 'react';
import './index.css';
const AppContext = React.createContext();
function GreenBox () {
return <div className='green-box'>
<AppContext.Consumer>
{(context) => context.value}
</AppContext.Consumer>
</div>
}
function BlueBox () {
return <div className='blue-box'><GreenBox/></div>
}
class RedBox extends React.Component {
render() {
return <div className='red-box'>
<AppContext.Consumer>
{(context) => context.value}
</AppContext.Consumer>
<BlueBox/>
</div>
}
}
class Context extends React.Component {
state = {
number: 10
}
render() {
return (
<AppContext.Provider value = {this.state.number}>
<RedBox/>
</AppContext.Provider>
)
}
}
export default Context;
The value you set in the Provider will be the argument received in the render props function in Consumer, so instead of accessing the number you're expecting with context.value, you should just change to context.

Simple React/Enzyme test failing over map issue

I have a simple react component with a simple test. It is failing for some reason. Can someone take a look at this?
Here is the component.
import React from 'react';
import ToDoItem from '../ToDoItem/ToDoItem';
export default class ToDos extends React.Component {
render() {
const toDoItems = this.props.items.map((item, key) => (
<ToDoItem item={item} key={key} />
));
return (
<section>
{ toDoItems }
</section>
)
}
}
Not rocket science. Here is the test:
it('displays all ToDo items passed as props', () => {
const items = ['example1', 'example2'];
const toDos = mount(<ToDos items={items} />);
expect(toDos.contains(<ToDoItem />)).toEqual(true);
});
The test seems very bothered by "TypeError: Cannot read property 'map' of undefined" It can't seem to read the items props. Am I not passing the array properly in the test? I can't see what's wrong here. The code itself works fine. It's just the test... Help!
you're not declaring any props in your component
constructor(props){
super(props)
}

passing an event to a child component in React

I'm new to React and this is a very noob question, but I don't understand why this is not working.
I'm trying to build a simple todo List.
My TodoList.js Component looks like this:
import React, {Component} from 'react';
import TodoItem from './TodoItem';
export default class TodoList extends Component{
constructor(props){
super(props);
this.state = {
todos:[
{
title:"todo1"
},
{
title:"todo3"
},
{
title:"todo2"
}
]
}
}
handleRemove(idx){
alert('works');
}
render(){
var todos = this.state.todos.map(function(t,idx){
return(<TodoItem
remove={this.handleRemove.bind(this,idx)}
title={t.title}
/>)
})
return (
<div>
<h1>To do</h1>
<div>{todos}</div>
</div>
)
}
}
My child Component looks like this:
import React, {Component} from 'react';
export default class TodoItem extends Component{
render(){
return (
<div>{this.props.title}
<button onClick={this.props.remove}>X</button>
</div>
)
}
}
But I get a TypeError with "Cannot read property 'handleRemove' of undefined". I'm wondering why inside the map function {this} is undefined?
I tried to put this this.handleRemove = this.handleRemove.bind(this) into the constructor.
Didn't change anything. Shouldn't this also be defined inside the .map() ?
You need to put this as the second argument
If a thisArg parameter is provided to map, it will be used as
callback's this value. Otherwise, the value undefined will be used as
its this value. The this value ultimately observable by callback is
determined according to the usual rules for determining the this seen
by a function.
on map:
render(){
var todos = this.state.todos.map(function(t,idx){
return(<TodoItem
remove={this.handleRemove.bind(this,idx)}
title={t.title}
/>)
}, this)
return (
<div>
<h1>To do</h1>
<div>{todos}</div>
</div>
)
}
}
Alternatively, you can use an ES6 arrow function to automatically preserve the current this context:
var todos = this.state.todos.map((t,idx) => {
return(<TodoItem
remove={this.handleRemove.bind(this,idx)}
title={t.title}
/>)
})

Cannot read property 'map' of undefined in ReactJS

I've got a problem with my ReactJS App with getting data from api. I still have an error: 'Cannot read property 'map' of undefined', and I have no idea why it's happening.
My code:
UsersList.js
import React from 'react';
import ReactDOM from 'react-dom';
import fetch from 'isomorphic-fetch';
import { Card, Container, Icon } from 'semantic-ui-react'
import User from './User'
class ProfilesList extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [],
fetched: false,
loading: false,
};
}
componentWillMount(){
this.setState({
loading : true
});
fetch('http://58be98154389c312007f403f.mockapi.io/users/users').then(res => res.json())
.then(res =>{
this.setState({
users : res.results,
loading : true,
fetched : true
});
});
}
render() {
const {fetched, loading, users} = this.state;
let content;
if(fetched){
content = <div>{this.state.users.map((user,index) =>
<User key={user.username} id={index+1} user={user}/>)}</div>;
}
else if(loading && !fetched){
content = <p> Loading ...</p>;
}
else{
content = (<div></div>);
}
return (
<div>
{content}
</div>
);
}
}
export default ProfilesList;
User.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Card, Container, Icon } from 'semantic-ui-react'
class User extends React.Component {
render() {
const {user, id} = this.props;
return (
<Card
image='http://semantic-ui.com/images/avatar/large/elliot.jpg'
header={user.username}
meta='Friend'
description='Elliot is a sound engineer living in Nashville who enjoys playing guitar and hanging with his cat.'
extra={(
<a>
<Icon name='user' />
16 Friends
</a>
)}
/>
);
}
}
export default User;
Thanks for your help!
Your state.users is undefined when you try to do this.state.users.map() in your render function. So task #1 is to figure out why your fetch() is returning undefined and fix that. It's a good idea to build in some handling for cases when you get undefined results or other errors and set your state appropriately. Additionally, I tend to check that an expected array is not undefined before I try to map it, like this:
{
expectedArray
?
expectedArray.map(someMappingFunction)
:
<div>expectedArray was 'undefined' or otherwise 'falsy'</div>
}
Such a conditional statement is called a "ternary" and is very useful because it can be embedded in JSX as an "if/else" statement. It has the form (condition) ? (expression if true) : (expression if false). For example:
var foo = 7;
var bar = (foo % 2 == 0) ? "Even" : "Odd";
console.log(bar); // "Odd"

Resources