React JS: Cannot read property [duplicate] - javascript

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I'm learning React; I have a such problem. When I call function "handleSearch" it crashes with TypeError: Cannot read property 'CONTACTS' of undefined on console.log(this.CONTACTS);
I define CONTACTS in constructior. And call method handleSearch() in onChange of input. Then the error occurs.
But everything is ok with this.CONTACTS.map()
import React, { Component } from 'react';
import Contact from './Contact';
import './Contacts.css';
class ContactList extends Component {
constructor() {
super();
this.CONTACTS = [
{
id: 1,
name: 'Alex',
phone: '777',
image: 'https://78.media.tumblr.com/2b5293dc3133abeab79aa74e151e74f9/tumblr_pa1h148ulz1rzp45wo1_75sq.jpg'
},
{
id: 2,
name: 'Ann',
phone: '888',
image: 'https://78.media.tumblr.com/2b5293dc3133abeab79aa74e151e74f9/tumblr_pa1h148ulz1rzp45wo1_75sq.jpg'
},
{
id: 3,
name: 'Zel',
phone: '999',
image: 'https://78.media.tumblr.com/2b5293dc3133abeab79aa74e151e74f9/tumblr_pa1h148ulz1rzp45wo1_75sq.jpg'
}
];
this.state = {
displayedContacts: this.CONTACTS
};
}
handleSearch(event) {
var query = event.target.value.toLowerCase();
console.log(this.CONTACTS);
}
render() {
return (
<div className="contacts">
<input type="text" className="search-field" onChange={ this.handleSearch }/>
<ul className="contacts-list">
{
this.CONTACTS.map(function(el) {
return <Contact
key={el.id}
name={el.name}
phone={el.phone}
image={el.image} />
})
}
</ul>
</div>
);
}
}
export default ContactList;

You have to use bind in the constructor. In your event handler this refers to the DOM node. Please add this line to the constructor:
this.handleSearch = this.handleSearch.bind(this)

Related

Why does passing props cause it to be embed inside an object?

Is there a way to pass a prop without embedding it inside the object?
For instance, consider the parent component passing the "partners" data
const partners = [
{
name: "Test1",
},
{
name: "Test2",
},
{
name: "Test3",
},
{
name: "Test4",
},
];
const Partners: NextPage = () => {
return (
<>
<PartnerPanel props={partners} />
</>
);
};
The child component
// incorrect type
type PropsType = [
{
name: string;
}
];
//correct type
type PropsType = { props: { name: string; }[]; }
export const PartnerPanel: FC<PropsType> = (props): JSX.Element => {
return <div>{props.props[0].name}</div>;
};
Why is it that the props are embedded inside another props, for instance, I have to do props.props[0].name to get the value? Instead of props[0].name
The nested props object is something you are doing, not something that happens automatically with props.
You have named a prop - props
<PartnerPanel props={partners} />
This is a confusing name. You should probably rename it to be clearer as partners.
<PartnerPanel partners={partners} />
Then you would access it more logically as
export const PartnerPanel: FC<PropsType> = (props): JSX.Element => {
return <div>{props.partners[0].name}</div>;
};
You will also need to change your type
type PropsType = { partners: { name: string; }[]; }

Trying to map over passed array of objects property in React

Started learning React and JS not too long ago.
I have a parent class 'App' that gets a an array of objects 'data' from data.js. App.js is sending that 'data' property down to the 'BookList' class. I am trying to map over said property in the BookList class and save elements in 'mappedBooks' but keep getting this error:
TypeError: this.props.books.map is not a function
DATA.JS:
const data = [
{
id: 1,
title: `The Pragmatic Programmer`,
author: `David Thomas, Andrew Hunt`,
img: `https://images-na.ssl-images-amazon.com/images/I/51cUVaBWZzL._SX380_BO1,204,203,200_.jpg`
},
{
id: 2,
title: `HTML and CSS: Design and Build Websites`,
author: `Jon Duckett`,
img: `https://images-na.ssl-images-amazon.com/images/I/31aX81I6vnL._SX351_BO1,204,203,200_.jpg`
},
{
id: 3,
title: `Coding All-in-one For Dummies`,
author: `Nikhil Abraham`,
img: `https://images-na.ssl-images-amazon.com/images/I/51RXaV0MGzL._SX397_BO1,204,203,200_.jpg`
},
{
id: 4,
title: `Learning React`,
author: `Alex Banks, Eve Porcello`,
img: `https://images-na.ssl-images-amazon.com/images/I/51FHuacxYjL._SX379_BO1,204,203,200_.jpg`
},
{
id: 5,
title: `Learning Web Design`,
author: `Jennifer Robbins`,
img: `https://images-na.ssl-images-amazon.com/images/I/51iVcZUGuoL._SX408_BO1,204,203,200_.jpg`
},
{
id: 6,
title: `JavaScript and JQuery: Interactive Front-End Web Development`,
author: `Jon Duckett`,
img: `https://images-na.ssl-images-amazon.com/images/I/41y31M-zcgL._SX400_BO1,204,203,200_.jpg`
},
{
id: 7,
title: `Head First JavaScript Programming`,
author: `Eric Freeman, Elisabeth Robson`,
img: `https://images-na.ssl-images-amazon.com/images/I/51qQTSKL2nL._SX430_BO1,204,203,200_.jpg`
},
{
id: 8,
title: `Learning Redux`,
author: `Daniel Bugl`,
img: `https://images-na.ssl-images-amazon.com/images/I/41gxBZ8GNpL._SX403_BO1,204,203,200_.jpg`
},
{
id: 9,
title: `Node.js 8 the Right Way`,
author: `Jim Wilson`,
img: `https://images-na.ssl-images-amazon.com/images/I/51t44mzlCaL._SX415_BO1,204,203,200_.jpg`
},
{
id: 10,
title: `PostgreSQL: Up and Running`,
author: `Regina Obe`,
img: `https://images-na.ssl-images-amazon.com/images/I/51FSjiYDfpL._SX379_BO1,204,203,200_.jpg`
},
{
id: 11,
title: `Fundamentals of Web Development`,
author: `Randy Connolly, Ricardo Hoar`,
img: `https://images-na.ssl-images-amazon.com/images/I/51xEzGTH6lL._SX402_BO1,204,203,200_.jpg`
},
{
id: 12,
title: `Web Design Playground`,
author: `Paul McFedries`,
img: `https://images-na.ssl-images-amazon.com/images/I/41-6F+RDbIL._SX258_BO1,204,203,200_.jpg`
}
]
export default data;
APP.JS
import React, {Component} from 'react'
import './App.css';
import BookList from './Components/BookList';
import Header from './Components/Header'
import Shelf from './Components/Shelf';
import data from './data'
class App extends Component {
constructor(){
super()
this.state ={
books : {data}
}
}
render(){
return (
<div className="App">
<Header/>
<BookList books={this.state.books}/>
<Shelf/>
</div>
);
}
}
export default App;
and BOOKLIST.JS:
import React, {Component} from 'react'
class BookList extends Component{
render(){
let mappedBooks = this.props.books.map(function(element){
return {element}
})
return(
<div className = 'BookList'>
<h1>list</h1>
</div>
)
}
}
export default BookList
in Data.js you've got
export default data;
and data is an array. So when you import data in App.js it's an array.
Try running this code snippet to get a better idea of what's going on here:
let data = [1,2,3,4]
console.log('when data is an array')
console.log('{data} is', {data})
data = {
'data': [1,2,3,4]
}
console.log('when data is an object with a property called data pointing to an array')
console.log('{data} is', {data})
console.log('but if you call a function and pass in data (as an object with data as a named property pointing to an array), you can use the curly braces to pull the array out of the object using destructuring')
function destructureData({data}) {
console.log(data)
}
destructureData(data)
So, when you do this:
this.state = {
books: { data }
}
it's actually an object property shorthand that's interpreted (in ES6) as this:
this.state = {
books: { data: data }
}
If you actually want this.state.books to be the array you imported from data.js then you set it directly:
this.state = {
books: data
}
Or, using that object property shorthand, and the fact that you've got data as a default export, you could change the import to this:
import books from './data'
And then do this:
this.state = {
books
}
If you'd like to read more about the destructuring syntax–where you use curly braces to pull data out of an object or an array–this article on MDN is a good read.

Parsing error: Unexpected token, expected ";" whenever I add a constructor?

Whenever I try to add a class constructor it shows this error, Unexpected token, expected ";"
I'm trying to use a constructor to initialize the internal component state but keeps giving this error. I've tried rewriting the code but it didn't work.
Without the constructor everything works fine, Please what I'm I missing?
See the image of the error
I just started learning to react last week
import React, { Component } from 'react';
import './App.css';
function App() {
constructor(props) {
super(props);
this.state = {
list,
github
};
}
const list = [
{
title: 'React',
url: 'https://facebook.github.io/react/',
author: 'Jordan Walke',
num_comments: 3,
points: 4,
objectID: 0,
},
{
title: 'Redux',
url: 'https://github.com/reactjs/redux',
author: 'Dan Abramov, Andrew Clark',
num_comments: 2,
points: 5,
objectID: 1,
},
];
const github = [
{
id: 1,
name: 'Sanusi Hayatu',
username: 'hamicch',
url: 'https://github.com/hamicch',
repos: 24
},
{
id: 2,
name: 'Hayatu Michael',
username: 'Azeez',
url: 'https://github.com/azeez',
repos: 30
},
{
id: 3,
name: 'Ridwan Abdulahi',
username: 'ridwan',
url: 'https://github.com/ridwan',
repos: 50
}
];
return (
<div className="App">
{list.map(item =>
<div key={item.objectID}>
<span>
<a href={item.url}>{item.title}</a>
</span>:
<span>{item.author}</span>--
<span>{item.num_comments}</span>--
<span>{item.points}</span>
</div>
)}
<h2>GitHub Accounts</h2>
{github.map(user =>
<div key={user.id} class='acc'>
<div>
<strong>Username: </strong>
<a href={user.url}>{user.username}</a>
</div>
<div>
<strong>Name: </strong> {user.name}
</div>
<div>
<strong>Repos: </strong>
{user.repos}
</div>
</div>
)}
</div>
);
}
export default App;
This is the error page
You cannot have constructor in functional component, it is reserved for class components only.
The shorthand for property: a_function can only be used in an object literal or class.
You can't use it where an expression or statement is expected.
class Foo {
constructor() {
this.ran = Math.random();
}
}
const foo = new Foo();
const bar = new Foo();
console.log(foo.ran);
console.log(bar.ran);
You're writing a function component. There's no class, so you aren't constructing an object, so having a constructor doesn't make sense anyway.

Can't access React js component's passed down value

I'm fairly new to react and i would like to know why i can't access my props that are passed down.
In my StatContentBet.js Component, i cannot access the props object values which i passed down from StatContent.js.
I can access this.props.img, but not this.props.bet.img, even though this.props.bet is a valid object.
https://gyazo.com/52347142134362b9cc4b7112c18ceaaf
Here is my StatContentBet.js (Where i'm trying to call the passed down from)
import React from "react";
import MiniDice from "./MiniDice";
class StatsContentBet extends React.Component {
render() {
return (
<div className="statsConentBet">
<div className="betInfo">
<img
className="betInfo-userImg"
src={this.props.img}
/>
<span className="betInfo-username">Richard Henricks</span>
<div className="betInfo-dices">
{this.props.betChoices.map((betChoice, index) => {
console.log(betChoice)
})}
</div>
</div>
</div>
);
}
}
export default StatsContentBet;
StatContent.js (Where i'm calling the
import React, { Component } from "react";
import StatContentBet from "./StatsContentBet";
class StatContent extends Component {
constructor() {
super();
this.state = {
};
}
render() {
let bets = [{
id:1,
username:"test",
img: "https://miro.medium.com/max/1200/1*mk1-6aYaf_Bes1E3Imhc0A.jpeg",
diceChoices: [1,2,3,4,5,6,1]
},{
id:2,
username:"test",
img: "https://miro.medium.com/max/1200/1*mk1-6aYaf_Bes1E3Imhc0A.jpeg",
diceChoices: [1,2,3,4,5,6,1]
},{
id:3,
username:"test",
img: "https://miro.medium.com/max/1200/1*mk1-6aYaf_Bes1E3Imhc0A.jpeg",
diceChoices: [1,2,3,4,5,6,1]
},{
id:4,
username:"test",
img: "https://miro.medium.com/max/1200/1*mk1-6aYaf_Bes1E3Imhc0A.jpeg",
diceChoices: [1,2,3,4,5,6,1]
}]
return (
<div id="statsContentContent">
{/* <StatContentBet img='https://miro.medium.com/max/1200/1*mk1-6aYaf_Bes1E3Imhc0A.jpeg' /> */}
{bets.map((bet, i) =>
<StatContentBet
key={i}
betChoices={bet.diceChoices}
bet={bet}
img={bet.img}
/>
)}
</div>
)
}
}
export default StatContent;
All the help is greatly appreciated!
It's working fine for me https://jsfiddle.net/hawk939393/19a7bgxL/4/; I'm not getting any errors related to undefined.
P.s. you just have a typo in a component name StatContentBet -> StatsContentBet
Edit: Make the following change inside your InputDices component:
StatsContentBet betChoices={[]}></StatsContentBet>
or you can check inside StatsContentBet whether this.props.betChoices is defined: if defined return jsx, else return something else return null

How to access properties of objects from a third-party DOM library used in a React component from the outside

I want to use Vis.js in a React based project. Since none of the Vis Network implementations work for me I have to use the plain library.
This is my test React component
import { DataSet, Network } from 'vis';
import React, { Component, createRef } from "react";
class VisNetwork extends Component {
constructor() {
super();
this.network = {};
this.appRef = createRef();
this.nodes = new DataSet([
{ id: 1, label: 'Node 1' },
{ id: 2, label: 'Node 2' },
{ id: 3, label: 'Node 3' },
{ id: 4, label: 'Node 4' },
{ id: 5, label: 'Node 5' }
]);
this.edges = new DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 }
]);
this.data = {
nodes: this.nodes,
edges: this.edges
};
this.options ={};
}
componentDidMount() {
this.network = new Network(this.appRef.current, this.data, this.options);
}
render() {
return (
<div ref={this.appRef} />
);
}
}
export default VisNetwork;
It's the only component mounted so far
ReactDOM.render(<VisNetwork />,document.getElementById('mynetwork'));
My question is how I can access the properties of the network, for example, to get or delete a node.
node = nodes.get(nodeId);
I read about React Ref and tried something like
() =>{ console.log(document.getElementsByClassName('vis-network')) as callback of ReactDOM.render()but that doesn't help.
Another question is why isn't the ref not set and it's just <div>.
Because I thought that this.appRef = createRef(); in the constructor of the component and ref={this.appRef} in render() would lead to a ref.
I hope you can give me a hint.
Actually the flow should be the other way round, define the nodes outside of the component, then pass them in. For that define the constructor as:
constructor(props) {
super(props);
this.nodes = props.nodes;
//...
}
Then construct it as:
const nodes = new DataSet([/*...*/]);
ReactDOM.render(<VisNetwork nodes={nodes} />,document.getElementById('mynetwork'));
Note that you should put anything stateful into this.state and use setState to mutate it.

Categories