Error handling while api limit exceeds in ReactJS - javascript

I'm new to ReactJs, this is the code for fetching data from truepush api.
export const getAllCampaign = () => {
return fetch(`https://api.truepush.com/api/v1/listCampaign/1`, {
method: "GET",
headers: {
Authorization: `${TOKEN}`,
"Content-Type": "application/json",
},
})
.then(response => {
return response.json()
})
.catch(err => console.log(err))
}
This api has limit, once the limit gets exceeds it shows an error of "campaigns.map not a function" at this place :
const allData = campaigns.map((campaign, i) => ({
...campaign,
...stats[i].data
}));
Here is my full code :
import React, {useState, useEffect} from 'react';
import {getAllCampaign, loadStats} from "../helpers/coreapihelpers";
const TableRow = () => {
const [campaigns, setCampaigns] = useState([]);
const [stats, setStats] = useState([]);
const loadAllCampaigns = () => {
getAllCampaign()
.then(data => { setCampaigns(data.data) })
.catch(err => { console.log(err) });
};
const loadAllStats = () => {
loadStats()
.then(data => { setStats(data) })
.catch(err => { console.log(err) });
}
useEffect(() => {
loadAllCampaigns();
loadAllStats();
}, [])
const allData = campaigns.map((campaign, i) => ({
...campaign,
...stats[i].data
}));
console.log(allData);
return (
<div className="container">
<div className="row">
<div className="col-xs-12">
<div className="table-responsive" data-pattern="priority-columns">
<table className="table table-bordered table-hover">
<thead>
<tr>
<th>Sr. No</th>
<th>Campaign Id</th>
<th>Campaign Name</th>
<th>Campaign Status</th>
<th>Reach</th>
<th>Sent</th>
<th>Delivered</th>
<th>Views</th>
<th>Clicks</th>
<th>Unsubscribers</th>
</tr>
</thead>
<tbody>
{allData.map(
(
{
campaignId,
campaignTitle,
campaignStatus,
Reach,
Sent,
Delivered,
Views,
Clicks,
Unsubscribers
},
index
) => (
<tr key={index}>
<td>{index + 1}</td>
<td>{campaignId}</td>
<td>{campaignTitle}</td>
<td>{campaignStatus}</td>
<td>{Reach}</td>
<td>{Sent}</td>
<td>{Delivered}</td>
<td>{Views}</td>
<td>{Clicks}</td>
<td>{Unsubscribers}</td>
</tr>
)
)}
</tbody>
</table>
</div>
</div>
</div>
</div>
);
}
export default TableRow;
How can i show a simple h1 tag saying limit exceeds when api limit exceeds or fails to fetch data ?

campaigns.map not a function basically this error means that your campaigns is not holding any data or array data to map on it. You can check it by consoling and debugging.
Since api is giving error , either you can take a error state and check while the promise is resolved whether the response is success or not, if not then set error as true and in campaign it will be [] so, use ?. which is chaining property to check if campaign is null or not if not then it searches for its key
const allData = campaigns?.map((campaign, i) => ({
...campaign,
...stats[i].data
}));
and in return of component put conditional statement:
return allData ?
<div className="container">
<div className="row">....
:<div>ERROR</div>

Related

How to group by two columns? ReactJS

The code that I posted below is the API request from which I make a table. This table has 4 columns: id, userid, title. I want to understand how I can sort by userid and title, as shown in the photo. It would be great if the steps were described in detail.
I'm trying to group the tab as shown in the photo, but I can't.
Can you suggest/show me how to do this?
Also wanted to know how to reset the group value of a column?
I will be grateful for any help.
My code:
import React from "react";
import "./GroupByUserID.css";
import { Link } from "react-router-dom";
export default class GroupByUserID extends React.Component {
// Constructor
constructor(props) {
super(props);
this.state = {
items: [],
};
}
componentDidMount = () => {
this.apiFetch();
};
//Fetch data from API
apiFetch = () => {
return fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => res.json())
.then((json) => {
this.setState((prevState) => {
return { ...prevState, items: json };
});
});
};
// Sort UserID
setSortedItemsUserID = () => {
const { items } = this.state;
const sortedUserID = items.sort((a, b) => {
if (a.userId < b.userId) {
return items.direction === "ascending" ? -1 : 1;
}
if (a.userId > b.userId) {
return items.direction === "ascending" ? 1 : -1;
}
return 0;
});
console.log(sortedUserID);
this.setState((prevState) => {
return { ...prevState, items: sortedUserID };
});
};
render() {
const { items } = this.state;
return (
<div>
<h1>Home Page</h1>
<table>
<thead>
<tr>
<th>
<Link target="self" to="/">
View Normal
</Link>
</th>
<th>Group By UserID</th>
</tr>
</thead>
<thead>
<tr>
<th>
User ID
<button
type="button"
onClick={() => this.setSortedItemsUserID()}
>
⬇️
</button>
</th>
<th>Title</th>
</tr>
</thead>
<tbody>
{items.map((item) => (
<tr key={item.userId + item.title}>
<td>{item.userId}</td>
<td>{item.title}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
}

tried a lot but not able to make deletehandler function working. here is my code

This is my librarylist component in which i pass deletehandler function to delete the row from library management. I don't know which part of the code is causing the problem. Any helps/suggestions are welcome.
LibraryBookList.js
const LibraryBookList = (props) => {
const[database, setDatabase]=useState()
const deleteHandler = (bookdataId) => {
const newDatabase=[...database];
const index= database.findIndex((bookdata)=>bookdata.id===bookdataId)
newDatabase.splice(index,1)
setDatabase(newDatabase);
} ;
return (
<ul className={classes.list}>
{props.database.map((bookdata) =>
(<LibraryBook
key={bookdata.key}
id={bookdata.id}
bookname={bookdata.bookName}
author={bookdata.author}
publisher={bookdata.publisher}
pages={bookdata.pages}
serialno={bookdata.serialNo}
onSelect={deleteHandler}
/>
))}
</ul>
)};
here i pass deletehandler via props
LibraryBook.js
const LibraryBook = (props) => {
return (
<li>
<table className={classes.table}>
<tbody>
<tr className={classes.table_row}>
<td className={classes.row_data}>{props.serialno}</td>
<td className={classes.row_data}>{props.pages}</td>
<td className={classes.row_data}>{props.bookname}</td>
<td className={classes.row_data}>{props.author}</td>
<td className={classes.row_data}>{props.publisher}</td>
<td>
<button className={classes.delete_btn} onClick={(props.onSelect(props.id))}>
Delete
</button>
</td>
</tr>
</tbody>
</table>
</li>
export default LibraryBookList;
**BookData.js **
const BookData = (props) => {
const [isLoading, setIsLoading] = useState(true);
const [loadedLibrarydata, setLoadedLibrarydata] = useState();
useEffect(() => {
setIsLoading(true);
fetch(
"https://librarymanagement-70ab2-default-rtdb.firebaseio.com/database.json"
)
.then((response) => {
// console.log('response',response.json())
return response.json();
})
.then((data) => {
const database = [];
console.log("data", data);
for (const key in data) {
const bookdata = {
id: key,
...data[key],
};
database.push(bookdata);
}
setIsLoading(false);
setLoadedLibrarydata(database);
});
}, []);
if (isLoading) {
return (
<section>
<p>Loading.....</p>
</section>
);
}
return (
<section>
<h1>Book Data Base</h1>
<table className={classes.table}>
<thead>
<tr className={classes.table_row}>
<th className={classes.row_heading}>Serial No</th>
<th className={classes.row_heading}>Pages</th>
<th className={classes.row_heading}>Book Name</th>
<th className={classes.row_heading}>Author</th>
<th className={classes.row_heading}>Publisher</th>
</tr>
</thead>
</table>
{loadedLibrarydata && loadedLibrarydata.length && (
<LibraryBooklist database={loadedLibrarydata} />
)}
</section>
);
};
export default BookData;
NewDataBase.js
const NewDataBase = () => {
const history=useHistory();
const addDataHandler = (bookData) => {
console.log('bookData',bookData);
fetch(
"https://librarymanagement-70ab2-default-rtdb.firebaseio.com/database.json",
{
method: "POST",
body: JSON.stringify(bookData),
headers: {
"Content-type": "application/json",
},
}
).then(()=>{
history.replace('/')
})
};
return (
<section>
<DataBaseForm onAddNewData={addDataHandler} />
</section>
);
};
export default NewDataBase;
The code has a few issues: 1) props.onSelect(props.id) inside onClick. Instead you should give a referance to that function. 2) You didn't have anything in database state before you click delete button. That is why ... spread operator didn't work 3) You are displaying props.database instead of database state. That is way the changes didn't show up even after you deleted a bookdata. I also fixed some small issues. Now it is working perfectly:
// !! you can put all the code into one file and run for testing.
// !! I removed stylings as I didn't have the source
import {useState, useEffect} from 'react'
const LibraryBooklist = (props) => {
const[database, setDatabase]=useState(props.database)
const deleteHandler = (bookdataId) => {
const newDatabase=database.filter((bookdata)=>bookdata.id!==bookdataId);
setDatabase(newDatabase);
}
return (
<ul>
{database.map((bookdata) =>
<LibraryBook
key={bookdata.id}
id={bookdata.id}
bookname={bookdata.bookName}
author={bookdata.author}
publisher={bookdata.publisher}
pages={bookdata.pages}
serialno={bookdata.serialNo}
onSelect={deleteHandler}
/>
)}
</ul>
)};
const LibraryBook = (props) => {
const {id, onSelect} = props
return (
<li>
<table>
<tbody>
<tr>
<td>{props.serialno}</td>
<td>{props.pages}</td>
<td>{props.bookname}</td>
<td>{props.author}</td>
<td>{props.publisher}</td>
<td>
<button onClick={() => onSelect(id)}>
Delete
</button>
</td>
</tr>
</tbody>
</table>
</li>
)}
const BookData = (props) => {
const [isLoading, setIsLoading] = useState(true);
const [loadedLibrarydata, setLoadedLibrarydata] = useState();
useEffect(() => {
setIsLoading(true);
fetch(
"https://librarymanagement-70ab2-default-rtdb.firebaseio.com/database.json"
)
.then((response) => {
// console.log('response',response.json())
return response.json();
})
.then((data) => {
const database = [];
for (const key in data) {
const bookdata = {
id: key,
...data[key],
};
database.push(bookdata);
}
setIsLoading(false);
setLoadedLibrarydata(database);
});
}, []);
if (isLoading) {
return (
<section>
<p>Loading.....</p>
</section>
);
}
return (
<section>
<h1>Book Data Base</h1>
<table>
<thead>
<tr>
<th>Serial No</th>
<th>Pages</th>
<th>Book Name</th>
<th>Author</th>
<th>Publisher</th>
</tr>
</thead>
</table>
{loadedLibrarydata && loadedLibrarydata.length && (
<LibraryBooklist database={loadedLibrarydata} />
)}
</section>
);
};
export default BookData;

React mapping rendering issue

I'm having a very perplexing issue that I wonder if anyone could help with. I have objects being mapped as arrays into some html(/jsx). The objects aren't rendering. Strangely, though, in the debugger it does show each value being attributed to the insertions in the html -- but it's not rendering. any ideas?
The picture below is an example of one object in the reservations array showing as mapping in the debugger, whereas the rendering actually stays as the second picture.
The axios http request, in a promise with another request:
const getReservations =
axios
.get(`${api_url}/reservations`, {
headers: {
'Authorization': `Bearer ${sessionStorage.token}`
}
})
.then((res) => {
setReservations(reservations => ([...reservations, ...res.data]));
})
const getRoomTypes =
axios
.get(`${api_url}/room-types`, {
headers: {
'Access-Control-Allow-Origin': `${ui_url}`,
'Authorization': `Bearer ${sessionStorage.token}`
}
})
.then((res) => {
setRoomTypes(roomTypes => ([...roomTypes, ...res.data]));
})
Promise.all([getReservations, getRoomTypes])
.catch(() => {
setError(connectionError);
});
}, []);
Which passes the data to the rendered component:
return (
<div>
<h2>Reservations</h2>
<Link className="button" to="/reservations/create">Create</Link>
<br />
<br />
<ReservationDiv error={error} resData={reservations} />
</div>
);
The component in which the objects are rendered:
const ReservationDiv = (props) => {
const reservations = props.resData;
const renderTableData = () => {
reservations.map((reservation) => {
const { id, user, guestEmail, roomTypeId, checkInDate,
numberOfNights } = reservation;
return (
<tr key={id}>
<td className="res">{id}</td>
<td className="user">{user}</td>
<td className="email">{guestEmail}</td>
<td className="room">{roomTypeId}</td>
<td className="date">{checkInDate}</td>
<td className="nights">{numberOfNights}</td>
</tr>
);
});
}
return (
<table>
<tbody>
<tr>
<th>ID</th>
<th>Input by</th>
<th>Guest Email</th>
<th>Room Type</th>
<th>Check-in Date</th>
<th># of Nights</th>
<th>Total</th>
</tr>
{renderTableData()}
</tbody>
</table>
);
}
I can also provide quoted code, but I figured the problem seems to be something more fundamental, since it's a difference between a representation of a thing and the thing itself
You need to return the mapped array of JSX objects
const renderTableData = () => {
return reservations.map((reservation) => {
//...

Search in custom table - React

I'm trying to make a table with api data searchable. I'm on my way, but unsure on how to proceed further.
Code looks like this:
const [searchTerm, setSearchTerm] = useState("");
const [searchResults, setSearchResults] = useState([]);
const handleChange = event => {
setSearchTerm(event.target.value);
};
useEffect(() => {
const results = apiData.filter(person =>
person.toLowerCase().includes(searchTerm)
);
setSearchResults(results);
}, [searchTerm]);
const renderPerson = (contact, index) => {
return (
<tr key={index}>
<td>{contact.ID}</td>
<td>{contact.Info.Name}</td>
<td>{contact.InfoID}</td>
<td>{contact.Info.DefaultEmail.EmailAddress}</td>
<td>{contact.Info.DefaultPhone.Number}</td>
<td>{contact.Info.InvoiceAddress.AddressLine1}</td>
</tr>
)
}
return (
<Fragment>
<input type="text" value={searchTerm} onChange={handleChange} placeholder="Søk.."></input>
<table id="myTable">
<thead>
<tr className="header">
<th>ID</th>
<th>Navn</th>
<th>Info Id</th>
<th>E-post</th>
<th>Telefon</th>
<th>Adresse</th>
</tr>
</thead>
<tbody>
{apiData.map(renderPerson)}
</tbody>
</table>
</Fragment>
)
https://dev.to/asimdahall/simple-search-form-in-react-using-hooks-42pg
I've followed this guide, but since I have the renderPerson function, I'm a bit unsure on how to handle this.
Question: Is there any way to get this working, or am I approaching it the wrong way? I'm aware that I need to put searchResult in the tbody somehow, but then the table won't be populated.
Any help is much appreciated
Edit: displaying code for getting apiData:
useEffect(() => {
getContacts()
}, [])
const getContacts = () => {
$.ajax({
url: `http://localhost:5000/getContacts`,
type: "POST",
data: ajaxObj,
success: (data) => {
let response = JSON.parse(data)
setApiData(response)
setLoading(false)
},
error: () => {
console.log("noe feilet?");
}
});
}
console.log(apiData)
Data looks like this:
data
Change apiData to searchResults on render
<tbody>
{searchResults.map(renderPerson)}
</tbody>
Change your filter way result (Updated)
const results = apiData.filter(person =>
person.Info.Name.toLowerCase().includes(searchTerm)
);
....
const renderPerson = (item, index) => {
return (
<tr key={index}>
<td>{item.ID}</td>
<td>{item.Info.Name}</td>
<td>{item.InfoID}</td>
<td>{item.Info.DefaultEmail.EmailAddress}</td>
<td>{item.Info.DefaultPhone.Number}</td>
<td>{item.Info.InvoiceAddress.AddressLine1}</td>
</tr>
)
}
Try this
export default function () {
const [searchTerm, setSearchTerm] = useState("");
const [searchResults, setSearchResults] = useState([]);
const apiData=[
{
ID:'1222',
Info:{
ID:'1222',
EmailAddress:'test#test.com',
Number:'2222222222',
AddressLine1:'test'
}
},
{
ID:'2333',
Info:{
ID:'2333',
EmailAddress:'test2#test.com',
Number:'1111111111',
AddressLine1:'test2'
}
}
]
const handleChange = event => {
setSearchTerm(event.target.value);
if(event.target.value){
const results = apiData.filter(person =>
person.ID.toLowerCase().includes(event.target.value)
);
setSearchResults(results);
}else{
setSearchResults([]);
}
};
const renderPerson = (contact, index) => {
return (
<tr key={index}>
<td>{contact.ID}</td>
<td>{contact.Info.Name}</td>
<td>{contact.Info.ID}</td>
<td>{contact.Info.EmailAddress}</td>
<td>{contact.Info.Number}</td>
<td>{contact.Info.AddressLine1}</td>
</tr>
)
}
return (
<Fragment>
<input type="text" value={searchTerm} onChange={handleChange} placeholder="Søk.."></input>
<table id="myTable">
<thead>
<tr className="header">
<th>ID</th>
<th>Navn</th>
<th>Info Id</th>
<th>E-post</th>
<th>Telefon</th>
<th>Adresse</th>
</tr>
</thead>
<tbody>
{searchResults.map(renderPerson)}
</tbody>
</table>
</Fragment>
)
}

Why it is giving me 'Cannot read property 'deleteProduct' of undefined' error react Js

I am getting an error when deleting one row in react js. error is 'Cannot read property 'deleteProduct' of undefined'. also is there any simple way to delete data from the database using custom api. below is my complete code for deleting data from the database.
Here is my code for deleting row-
import React from 'react';
import ReactDOM from 'react-dom';
export default class FetchedData extends React.Component{
constructor(props){
super(props);
this.state={
UserData:[],
response: {}
};
this.headers=[
{key:1,label:'Name'},
{key:2,label:'Department'},
{key:3,label:'Marks'},
];
this.deleteProduct=this.deleteProduct.bind(this);
}
componentDidMount(){
this.lookupInterval = setInterval(() => {
fetch("https://www.veomit.com/test/zend/api/fetch.php")
.then(response => {
return response.json();
})
.then(result => {
this.setState({
UserData:result
})
.catch(error => {
console.log(
"An error occurred while trying to fetch data from Foursquare: " +error
);
});
});
}, 500)
}
deleteProduct(userId) {
const { UserData } = this.state;
const apiUrl = 'https://www.veomit.com/test/zend/api/delete.php';
const formData = new FormData();
formData.append('userId', userId);
const options = {
method: 'POST',
body: formData
}
fetch(apiUrl, options)
.then(res => res.json())
.then(
(result) => {
this.setState({
response: result,
UserData: UserData.filter(item => item.id !== userId)
});
},
(error) => {
this.setState({ error });
}
)
}
render(){
return(
<div>
<table class="table table-bordered">
<thead>
<tr>
{
this.headers.map(function(h) {
return (
<th key = {h.key}>{h.label}</th>
)
})
}
</tr>
</thead>
<tbody>
{
this.state.UserData.map(function(item, key) {
return (
<tr key = {key}>
<td>{item.name}</td>
<td>{item.department}</td>
<td>{item.marks}</td>
<td><span onClick={() => this.deleteProduct(item.id)}>Delete</span></td>
</tr>
)
})
}
</tbody>
</table>
</div>
);
}
}
Please help me remove this error.
thanks in advance.
Your mapping function is creating a new scope:
this.state.UserData.map(function(item, key) {
return (
<tr key = {key}>
<td>{item.name}</td>
<td>{item.department}</td>
<td>{item.marks}</td>
<td><span onClick={() => this.deleteProduct(item.id)}>Delete</span></td>
</tr>
)
})
Making it an arrow function should solve the issue:
this.state.UserData.map((item, key) => {
return (
<tr key = {key}>
<td>{item.name}</td>
<td>{item.department}</td>
<td>{item.marks}</td>
<td><span onClick={() => this.deleteProduct(item.id)}>Delete</span></td>
</tr>
)
})
This is probably due to losing context here:
{
this.state.UserData.map(function(item, key) {
return (
<tr key = {key}>
<td>{item.name}</td>
<td>{item.department}</td>
<td>{item.marks}</td>
<td><span onClick={() => this.deleteProduct(item.id)}>Delete</span></td>
</tr>
)
})
}
Change the function to an arrow function to autobind the callback:
{
this.state.UserData.map((item, key) => {
return (
<tr key = {key}>
<td>{item.name}</td>
<td>{item.department}</td>
<td>{item.marks}</td>
<td><span onClick={() => this.deleteProduct(item.id)}>Delete</span></td>
</tr>
)
})
}

Categories

Resources