Cannot read property 'map' of undefined with REACTJS - reactjs

I am new with reactjs.
This is what I am trying
class EventDemo extends Component {
constructor(){
super()
this.getStarWars()
this.state = {}
}
getStarWars = ()=> axios.get('https://swapi.co/api/people')
.then(res => {
console.log(res.data)
this.setState({
names: res.data.results
})
})
render() {
console.log(this.state.names);
return (
<div>
{this.state.names.map(function(e){
return <li>{e.name}</li>
})}
</div>
);
}
}
But This following error i am getting
What I am doing wrong here ? It supposed to work .

First of all,you shouldn't call your this.getStarWars() function inside the constructor, it is a very bad practice and could cause you troubles, http calls in React component should be generally called from the componentDidMount function.
However the issue in this case is another one,you haven't given an initial value to this.state.names, so when the component tries to do the initial render it fails because the names are undefined since the initial render appens before the http call is resolved
You code should be fixed like this:
class EventDemo extends Component {
constructor(){
super()
this.state = { names:[] }
}
componentDidMount(){
this.getStarWars()
}
getStarWars = ()=> axios.get('https://swapi.co/api/people')
.then(res => {
console.log(res.data)
this.setState({
names: res.data.results
})
})
render() {
console.log(this.state.names);
return (
<div>
{this.state.names.map(function(e){
return <li>{e.name}</li>
})}
</div>
);
}
}

Related

Why is the data from my API is not display

import React, { Component } from 'react'
class Newsgenerator extends Component {
constructor(){
super()
this.state = {
data:{}
}
}
componentDidMount() {
fetch("https://newsapi.org/v2/everything?q=Apple&from=2021-06-24&sortBy=popularity&apiKey={...}")
.then(response => response.json())
.then(news => {
this.setState({
data: news
})
console.log(news)
})
}
render() {
return (
<div>
{this.state.data.discription}
</div>
)
}
}
export default Newsgenerator
You have a few things going on here. First off, this.state.data.discription doesn't exist. When your API call response, you get an object like this which you set to this.state.data:
{
status: "ok",
totalResults: 1588,
articles: [...]
}
So this.state.data.discription is undefined. So what you're seeing is the result of trying to print an undefined variable - which in React is nothing.
My guess is that you want to print the articles, which means your return statement should look more like this:
return (
<div>
{this.state.data.articles.map((article, idx) => {
return (<h2 key={`article-${idx}`}>{article.title}</h2>)
}}
</div>
)
What you have in this code is an array of articles in your state.data, and you're iterating through that to print the article title (title in your api response).
This is the starting point and should set you in the right direction.

Error: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application

I'm getting the above error and I don't know how to handle it.
I got a component. And in the render() i'm looping through an array and placing another component and parsing a value to that component like this:
render() {
let allProducts = this.state.products.map((product, i) => {
return (
<div key={product.article}>
...
<PriceStock value={product.article} />
...
</div>
)
})
}
In the PriceStock component i'm fetching some data with axios like the code below:
export default class PriceStock extends React.Component {
constructor(props) {
super(props);
this.state = ({
buttoprice: ''
})
this.getPriceAndStock = this.getPriceAndStock.bind(this)
}
getPriceAndStock(articleNo) {
return axios.post('LINK_TO_URL', {
articleNo: articleNo
}).then(result => {
return result.data
})
}
async componentDidMount() {
let pricestock;
pricestock = await this.getPriceAndStock(this.props.value)
let bruttoPrice = PRICE_TO_PARSE_TO_THE_STATE;
this.setState({ buttoprice: bruttoPrice })
}
render() {
return (
<div >
{this.state.buttoprice}
</div>
);
}
}
The error seems to happen when I try to setState in the componentDidMount, any suggestions?
this is an error occurs because you are updating state before it gets initialized
perform your loading activities in the constructor it is the right way to do it
getPriceAndStock(orderNumber, articleNo) {
return axios.post('LINK_TO_URL', {
orderNr: orderNumber, vareNr: articleNo
}).then(result => {
return result.data
})
}
constructor() {
this.getPriceAndStock(this.props.value)
.then(pricestock=>{
let bruttoPrice = PRICE_TO_PARSE_TO_THE_STATE;
this.state({ buttoprice: bruttoPrice })
})
.catch(console.log)
}
Found the answear in this question: https://github.com/material-components/material-components-web-react/issues/434
It's remindend me a little bit about the comment with another stackoverflow question.

Passing data to another component does not working

first of all I am pretty new to react and developing a react app. In my app, I am fetching data from an api inside componentDidmount()
constructor(props){
super(props);
this.state={
employeeData:[]
}
}
componentDidMount(){
axios.get("http://localhost:8080/hris/api/employee/123456/personal?authToken=ldkasjfdsoue",
)
.then(response => response.data)
.then((data) => {
this.setState({ employeeData: data },()=>
//console.log("dfdf"+JSON.stringify(this.state.employeeData['employeeID'])))
**// i am getting the data here**
})
.catch(err=> console.log("whyerror"+err))
}
I stored this data into state. But when I want to send data into another component, error occurs.
{console.log("isdata"+JSON.stringify(this.state.employeeData))}
{/* {<Table data={this.state.employeeData}/> } */}
here I am getting all data, but when I am doing this
{console.log("isdata"+JSON.stringify(this.state.employeeData))}
{<Table data={this.state.employeeData}/> }
Table.js
constructor(props){
super(props);
console.log('thisprops'+JSON.stringify(props)) //giving null value
}
This shows that the Table component received null props.
Now how can I pass data to Table component ?
What error occurs? Is employeeData an array? If so then you can make the initial employeeData as an empty array like;
ParentComponent.jsx
export class ParentComponent extends Component {
constructor(props) {
super(props)
this.state = {
employeeData: []
}
}
componentDidMount(){
axios.get("http://localhost:8080/hris/api/employee/123456/personal?authToken=ldkasjfdsoue",
)
.then(response => response.data)
.then((data) => {this.setState({ employeeData: JSON.stringify(data)})
.catch(err=> console.log("whyerror"+err))
}
render(){
return (
<Table data={this.state.employeeData}/>
)
}
}
Table.jsx
export class Table extends Component {
componentDidMount(){
console.log(this.props.data) // it should be here
}
render(){
return (
{
this.props.data && this.props.data.map((employee) => {
...
})
}
)
}
}
<Table data={this.state.employeeData}/>
No need to wrap with brackets, this is JSX and not javascript
better yet do this
<Table data={JSON.stringify(this.state.employeeData)}/> to avoid standalone code

ReactJS - Pass Updated Value To Sub-Component Method

I'm working on an environment that is basically set up with a Main Component like this:
class MainComponent extends Component {
constructor(props) {
super(props);
this.state = {
selectedValues: []
};
}
render() {
const { selectedValues } = this.state;
return (
// Other components
<SubComponent selectedValues = {selectedValues} />
// Other components
);
}
}
export default MainComponent;
And a Sub Component like this:
class SubComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
isExporting: false,
selectedValues: props.selectedValues
};
}
performTask = () => {
this.setState({ isWorking: true });
const { selectedValues } = this.state;
console.log(`Selected Values: ${selectedValues}`);
fetch('/api/work', {
method: 'GET'
})
.then(res => res.json())
.then((result) => {
// Handle the result
this.setState({ isWorking: false });
})
.catch((error) => {
console.log(error);
this.setState({ isWorking: false });
});
};
render() {
const { isWorking } = this.state;
return (
<Button
bsStyle="primary"
disabled={isWorking}
onClick={() => this.performTask()}
>
{isWorking ? 'Working...' : 'Work'}
</Button>
);
}
}
SubComponent.propTypes = {
selectedValues: PropTypes.arrayOf(PropTypes.string)
};
SubComponent.defaultProps = {
selectedValues: []
};
export default SubComponent;
In the Main Component, there are other components at work that can change the selectedValues. The functionality I'd like to see is that when the performTask method fires, it has the most recent and up to date list of selectedValues. With my current setup, selectedValues is always an empty list. No matter how many values actually get selected in the Main Component, the list never seems to change in the Sub Component.
Is there a simple way to do this?
I would suggest you 2 of the following methods to check this problem:
Maybe the state.selectedItems doesn't change at all. You only declare it in the contractor but the value remains, since you didn't setState with other value to it. Maybe it will work if you will refer to this.props.selectedItems instead.
Try to add the function component WillReceiveProps(newProps) to the sub component and check the value there.
If this method doesn't call, it means the selectedItems doesnt change.
Update if some of it works.
Good luck.
selectedValues in SubComponent state has not updated since it was set in SubComponent constructor. You may need to call setState again in componentWillReceivedProps in SubComponent

Getting undefined on state when accessing from child to parent - React

I have a problem where in I'm going to access a state inside a method inside my parent component from my child component it returns me an undefined value which i'm sure in the first place have a value of objects in an array.
Parent Component:
class BoardList extends React.Component {
constructor(props){
super(props);
this.state = {
lists: []
};
}
componentWillMount(){
this.props.getBoardLists()
.then((result) => {
this.setState({
lists: result
});
})
.catch(error => {
console.log(error);
});
}
addBoardLists(result){
// This is i'm getting my undefine state lists :(
console.log(this.state.lists);
this.setState({
lists: this.state.lists.concat([result])
});
}
render() {
const { isLoading,data } = this.props;
if(isLoading){
return (
<Loading />
);
}
return (
<div className={style.boardListContainer}>
<h1 className={style.boardListTitle}>Personal Board</h1>
<Row>
<BoardItem item={this.state.lists} />
<BoardAdd onDisplay={this.fetchBoardLists} onAddItem={this.addBoardLists} />
</Row>
</div>
)
}
}
Child Component:
class BoardAdd extends React.Component {
constructor(props){
super(props);
this.state = {
name: '',
boardAddModalShow: false
}
}
openAddBoardModal(){
this.setState({ boardAddModalShow: true });
}
closeAddBoardModal(){
this.setState({ boardAddModalShow: false });
this.props.dispatch(reset('BoardAddModalForm'));
}
addBoard(formProps) {
this.props.addBoard(formProps).then((result) => {
// This is where I access my addOnItem from my parent component
this.props.onAddItem(result);
this.props.dispatch(reset('BoardAddModalForm'));
this.closeAddBoardModal();
})
.catch(error => {
console.log("error");
console.log(error);
});
}
}
Perhaps this will help?
class BoardList extends React.Component {
constructor(props){
super(props);
this.state = {
lists: []
};
this.addBoardList.bind(this)
}
What is this magical .bind? You should read up on what this means in JavaScript (which it almost never thinks what you think it means). By default, ES6 constructors do not bind (for some crazy reason in my opinion), their own methods to their own this value. Thus, the this in your method is referring to a completely different this you are thinking of and consequentially, making this scenario quite bizarre.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/this

Resources