Cannot read property 'map' of undefined in React + Phoenix framework - json

I'm new to React. I have provided Postgresql API and I want to add those data in Material UI Table.
I've made some mistakes and I'm unable to figure to out.
I'm using API calls for the first time using Axios. So please guide me to solve this issue.
I'm using React.js for frontend work, Phoenix framework for backend, and PostgreSQL database.
The below component is used to handle API request using Axios
import axios from "axios"
import MedicineCard from './MedicineCard'
class Medicines extends React.Component {
constructor() {
super();
this.state = { medicines: [] };
}
componentWillMount() {
axios.get('http://localhost:4000/medicines')
.then(response => {
this.setState({ medicines: response.data.medicines });
})
.catch(error => {
console.log(error);
});
}
render() {
const posts = this.state.medicines.map((medicine, index) =>
<MedicineCard
key = { index }
medid = {medicine.medid}
medname = {medicine.medname}
/>
)
return (
<div>
{posts}
</div>
)
}
}
export default Medicines
Below Component is used for Material UI Table
import React from 'react'
import MaterialTable from 'material-table'
class MedicineCard extends React.Component{
render(){
const data=[
{medid:this.props.medid,medname:this.props.medname}
]
const column=[
{
title:'Medicine_ID',field:'medid'
},
{
title:'Medicine_Name',field:'medname'
}
]
return (
<div>
<MaterialTable title="Material Table"
data={data}
column ={column}
/>
</div>
);
}
}
export default MedicineCard
This component is used to display UI
import React from 'react'
import Medicines from './Medicines'
const Test = () => (
<div>
<Medicines />
</div>
)
export default Test
Please help me and guide me out to solve this issue

Related

How retrieve data from an API in JSON to a list in React.Js

I am trying to retrieve data from an API in React.Js but there is an small issue with the componentDidMount function.
Here is the API https://projects.cmsbox.in/app/bms/movie/public/api/upcomingMovie
I have tried this code with other API and it worked but in this case its not working. Also checked the API in Postman and everything seems to be fine.
Thanks in advance :)
import React, { Component } from 'react';
import './index.css';
import MovieCard from './moviecard'
import Homepage from './homepage';
import { render } from '#testing-library/react';
class UpcommingMovies extends Component{
constructor(props){
super(props);
this.state = {
upcmngmovie_list: [],
dataList:[],
isLoaded:false,
}
}
componentDidMount(){
fetch('https://projects.cmsbox.in/app/bms/movie/public/api/upcomingMovie')
.then(response=>response.json())
.then(data=>{
this.setState({
isLoaded:true,
dataList:data,
upcmngmovie_list:dataList,
})
});
}
render(){
var{isLoaded,upcmngmovie_list}=this.state;
function upcomngmoviecards(val){
return(
<div className="row"><MovieCard image={val.image} movie_name={val.movie_name}/></div>
);
}
if(!isLoaded){
return <div>Loading...</div>;
}
else{
return (
<>
<Homepage />
<div className="main">
<h3>Upcomming Movies</h3>
<div className="cardlist">
{upcmngmovie_list.map(upcomngmoviecards)}
</div>
</div>
</>
)
}
}
}
export default UpcommingMovies;
The api does not return an array it is returning an object. Array is in "Movie_list" property. Update your set state function to use the property.
this.setState({
isLoaded:true,
dataList:data,
upcmngmovie_list:data.Movie_list,
})

Passing props in react - fetching

I'm simply trying to pass props through components and render it in jsx but somehow that wouldn't work. I was searching for the problem but just cannot find it.
I'm trying pass props from this component:
import React from "react";
import "../styles/Products.css";
import ProductItem from "../items/ProductItem";
class Products extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentDidMount() {
fetch("../products.json")
.then(response => response.json())
.then(response => this.setState({ data: response.products }));
}
render() {
return (
<div className="products-container">
<ProductItem data={this.state.data[0]} />
</div>
);
}
}
export default Products;
to this component:
import React from "react";
import "../styles/ProductItem.css";
const ProductItem = props => {
console.log(props.data, "current");
return (
<div className="product-item">
<img src="" alt="" className="bike-image" />
<div className="active-product" />
<div className="view-details">Compare</div>
<h2>Bike</h2>
<h4>downhill bike</h4>
<p>3500 PLN</p>
</div>
);
};
export default ProductItem;
And the problem is when I'm looking in my react dev tools, props has passed properly, but when I'm trying to get to attributes of the object like props.data.id, I get an error:
Cannot read property 'id' of undefined
fetch needs some time to get the response and populate the this.state.data array. So you need to check if the this.state.data[0] value is really available or not. You can try this-
render() {
return (
<div className="products-container">
{this.state.data && this.state.data.length > 0 && <ProductItem data={this.state.data[0]} />}
</div>
);
}

Get JSON Data in multiple components using reactjs and redux

I would like to show data from a single API to different components as I want to hit the API only once and distribute the data to multiple small components. I know I can do this by using redux state but not sure how to do it. Need your help to achieve this. Below is the code done so far.
homepage/index.js
import SlidingBanner from './banner/BannerList';
import Celebslider from './celebrityslider/CelebSlider';
class HomePage extends Component {
render() {
return (
<div>
<SlidingBanner />
<anotherslider />
</div>
);
}
}
export default HomePage;
BannerList.js
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { itemsFetchData } from '../../../actions/items';
class BannerList extends Component {
componentDidMount() {
this.props.fetchData();
}
render() {
let bannerArray = [];
let banner = this.props.items.banner
for (let key in banner) {
bannerArray.push(banner[key]);
return (
<div>
<Slider {...slidersettings}>
{this.props.items.banner.map((item) => (
<div key={item.id}>
<img src={item.image_url} className="img-responsive"/>
</div>
))}
</Slider>
</div>
);
}
if (this.props.hasErrored) {
return <p>Sorry! There was an error loading the items</p>;
}
if (this.props.isLoading) {
return <p>Loading…</p>;
}
return (null);
}
}
BannerList.propTypes = {
fetchData: PropTypes.func.isRequired,
items: PropTypes.object.isRequired,
hasErrored: PropTypes.bool.isRequired,
isLoading: PropTypes.bool.isRequired
};
const mapStateToProps = (state) => {
return {
items: state.items,
hasErrored: state.itemsHasErrored,
isLoading: state.itemsIsLoading
};
};
const mapDispatchToProps = (dispatch) => {
return {
fetchData: (url) => dispatch(itemsFetchData(url))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(BannerList);
anotherslider.js
Now in this file, i want to fetch another array of objects or object from the same API.
I tried to mount the API in container component but did not worked, I hope i am doing some mistake. Please correct.
If you want to fetch data in anotherslider.js file you must connect reducer to class/function inside it as well as you are making it in BannerList.js file.
Now before render call componentWillReceiveProps(nextProps) function and you will get your data here.
If you want to call data in both of the sliders, you have 2 ways to handle it.
Make your redux requests in HomePage.js component and bind the data to the other components.
When you get the data on BannerList.js component, your state will be updated. Just add the redux connection to your anotherslider.js component and get data when updated.
const mapStateToProps = (state) => {
return {
items: state.items,
hasErrored: state.itemsHasErrored,
isLoading: state.itemsIsLoading
};
};
export default connect(mapStateToProps, mapDispatchToProps)(HomeList);
Apart from all these options, you can also use react's Context API as Provider/consumer to distribute your data among small components... this will save you passing props to all small components and directly access the value in component using Context.Consumer .. moreover if you do not want to store this state in global redux store, context API will save you from it...

Why I am getting `this.props.data is undefined` error?

I was egzecuting tutorial:
CLICK
And I am getting error: this.props.data is undefined.
I was implementing the tutorial in my test application, where I was testing also various React tools, so I have not copy-pasted it in 100%. I am using ASP.NET Core MVC and React, own architecture (for test application) and I did not installed all npm's from the tutorial. But I belive, that it is syntax or architecture problem. I am guessing, that calling server's data is corrupted somehow in app.js or CommentBox.js.
Error from console:
TypeError: this.props.data is undefined[Więcej informacji] bundle.js line 541 > eval:45:17
The above error occurred in the <CommentList> component:
in CommentList (created by CommentBox)
in div (created by CommentBox)
in CommentBox (created by App)
in div (created by App)
in div (created by App)
in App
Consider adding an error boundary to your tree to customize error handling behavior.
react-dom.development.js:14226
[Przełącz szczegóły wiadomości] TypeError: this.props.data is undefined[Więcej informacji]
Main app.js file that returns to index.js:
(...)
return (
<div className="App">
<div className="App-header">
Welcome to React!
<AddProject addProject={this.handleAddProject.bind(this)}/>
<Projects onDelete={this.handleDeleteProject.bind(this)} projects={this.state.projects} />
<CommentBox url="/comments" pollInterval={2000}/>
</div>
</div>
);
(...)
In my component folder all parent and children files:
CommentBox.js:
import React, { Component } from 'react';
import $ from 'jquery';
import uuid from 'uuid';
import CommentList from '../components/CommentList';
import CommentForm from '../components/CommentForm';
class CommentBox extends React.Component {
constructor(props) {
super(props);
this.state = { data: this.props.initialData };
}
loadCommentsFromServer() {
const xhr = new XMLHttpRequest();
xhr.open('get', this.props.url, true);
xhr.onload = () => {
const data = JSON.parse(xhr.responseText);
this.setState({ data: data });
};
xhr.send();
}
componentDidMount() {
this.loadCommentsFromServer();
window.setInterval(() => this.loadCommentsFromServer(), this.props.pollInterval);
}
render() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm/>
</div>
);
}
}
export default CommentBox;
CommentList.js:
import React, { Component } from 'react';
import $ from 'jquery';
import uuid from 'uuid';
import Comment from '../components/Comment';
class CommentList extends React.Component {
render() {
var commentNodes = this.props.data.map(function (comment) {
return (
<Comment name={comment.name} key={comment.productID}>
</Comment>
);
});
return (
<div className="commentList">
{commentNodes}
</div>
);
}
}
export default CommentList;
Comment.js:
import React, { Component } from 'react';
import $ from 'jquery';
import uuid from 'uuid';
class Comment extends React.Component {
rawMarkup() {
const md = new (global.Remarkable || window.Remarkable)();
const rawMarkup = md.render(this.props.children.toString());
return { __html: rawMarkup };
}
render() {
return (
<div className="comment">
<h2 className="commentName">
{this.props.name}
</h2>
{this.props.children}
</div>
);
}
}
export default Comment;
First, way too much code. Try to be as concise as possible.
Your issue is that this.state.data in CommentBox is undefined / null initially. Make sure that you're passing the initialData prop into CommentBox or handling the null case in CommentList
var commentNodes = (this.props.data || []).map(function (comment) {
return (
<Comment name={comment.name} key={comment.productID}>
</Comment>
);
});

Display API data using Axios and a list in React

I'm attempting to make a request to this https://www.themoviedb.org/documentation/api API in a React project and then display JSON data on my site.
I'm using Axios to make the request and I have been able to make the request and get the appropriate JSON data and console.log it or view it in the React tools in Firefox. However, I am having difficulty displaying the data in a ul. Initially I had an error pertaining to having a unique key for each list item, and I have since resolved that (or so I believe).
Here's my request and how I am attempting to render the data:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from "axios";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
posts: []
}
}
componentDidMount() {
axios.get(`https://api.themoviedb.org/3/movie/now_playing?api_key=*apikeyhere*&language=en-US&page=1`)
.then(res => {
const posts = res.data.results.map(obj => [obj.title, obj.overview]);
this.setState({ posts });
});
}
/* render() {
return (
<div>
<h1>Movie API data</h1>
<ul>
{this.state.posts.map(post =>
<li key={post.toString()}>{post.title}</li>
)}
</ul>
</div>
);
}
}
*/
render() {
return (
<ul>
{this.state.posts.map(function(post, index){
return (
<div key={index}>
<h1>{post.title}</h1>
<p>{post.overview}</p>
</div>
)
}
)}
</ul>
);
}
}
As you can see I attempted multile approaches to rendering this. What's wrong with my code and why isn't the JSON data rendering in the ul on my site?
I think, you have an error inside success fuction ({title: obj.title, overview: obj.overview})
componentDidMount() {
axios.get(`https://api.themoviedb.org/3/movie/now_playing?api_key=*apikeyhere*&language=en-US&page=1`)
.then(res => {
const posts = res.data.results.map(obj => ({title: obj.title, overview: obj.overview}));
this.setState({ posts });
});
}