React mapping rendering issue - javascript

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) => {
//...

Related

Loop over object and array of objects in React

Calling an API i get this data
{
"count":33,
"results":
[
{"id":365,"firstName":"Maisha","lastName":"Rawlings"},
{"id":613,"firstName":"Lettie","lastName":"Epps"},
{"id":433,"firstName":"Rocco","lastName":"Gant"},
{"id":856,"firstName":"Tova","lastName":"Coyle"},
{"id":896,"firstName":"Tari","lastName":"Mancuso"},
{"id":79,"firstName":"Tora","lastName":"Prince"},
{"id":59,"firstName":"Lashon","lastName":"Dunaway"},
{"id":378,"firstName":"Corey","lastName":"Schaffer"},
{"id":33,"firstName":"Nanci","lastName":"Middleton"},
{"id":390,"firstName":"Carmon","lastName":"Lavender"}
]
}
Which i have it in here for testing purposes
https://mocki.io/v1/d676e413-6659-4410-a8a3-7d5636f4b719
I have the next app made in React
const USERS_URL = "https://mocki.io/v1/d676e413-6659-4410-a8a3-7d5636f4b719";
export default function Table() {
const [names, setNames] = useState([]);
useEffect(() => {
async function getData() {
let response = await fetch(`${USERS_URL}`);
response = await response.json();
console.log(response);
setNames(response);
}
getData();
}, []);
return (
<div>
<table className="table">
<thead>
<tr>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
</thead>
<tbody>
{
names
&&
Object.entries(names).map(([key, value, idx]) => {
return <tr key={key}>
<td>{names.key}</td>
<td>{value.results[key]}</td>
{console.log(key, value)}
</tr>
})
}
</tbody>
</table>
</div>
);
}
I can't find the way to loop over "results", which is an array of objects. Any hint please?
Sollution
names.results.map((val,index)=>{
console.log("object",val)
})
us hte . we can access the properties inside and Object first access the result array in the object and then map() on it

Calling async method in React functional component

I have a question about a good way to solve this problem I have in React. I need to gather currencies from my own API that I've created, that works perfectly and I iterate it in my return statement of the React component. When iterating, I want to use the "item.pairs" data to use as an argument for a method call (async method) to get price information and render it. How can this be accomplished?
I added a method getCurrencyData, I tried calling that in the return statement inside the loop, but it will not work, and I have searched for this and it's not possible to do that in that way. So how can I do this?
The used code is below:
const Start = () => {
let match = useRouteMatch()
const [currencies, setCurrencies] = useState([])
const [currencyPrices, setCurrencyPrices] = useState([])
useEffect(() => {
getAllCurrencies()
}, [])
const getCurrencyData = async (ticker) => {
try {
const response = await KrakenService.getByTicker(ticker)
return Object.values(response.data.result)[0].c[0]
} catch (err) {
console.log(err)
}
}
const getAllCurrencies = async () => {
try {
const response = await CryptoCurrencyService.getAll()
setCurrencies(response.data.results)
} catch (err) {
console.log(err)
}
}
return(
<div className='Start'>
<Switch>
<Route path={`${match.path}/:currencyId`}>
test
</Route>
<Route path={match.path}>
<Container className="cc-container">
<Row>
<Table hover className="cc-table">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Price</th>
<th>24h %</th>
<th>7d %</th>
<th>Market Cap</th>
<th>Volume (24h)</th>
<th>Circulating Supply</th>
<th>Last 30 Days</th>
</tr>
</thead>
{currencies &&
currencies.map((item, index) =>
<tbody>
<tr>
<td>{index + 1}</td>
<td><Image src={item.logo} width="38" roundedCircle /> {item.name}</td>
<td>{item.pairs}</td> HERE I WANT TO FETCH DATA
</tr>
</tbody>
)
}
</Table>
</Row>
</Container>
</Route>
</Switch>
</div>
)
}
export default Start
Maybe create component for Price information?
// PriceInformation component
const PriceInformation = ({ ticker }) => {
const [priceInfo, setPriceInfo] = useState(null)
useEffect(() => {
getCurrencyData(ticker)
}, [])
const getCurrencyData = async (ticker) => {
try {
const response = await KrakenService.getByTicker(ticker)
setPriceInfo(Object.values(response.data.result)[0].c[0]);
// return Object.values(response.data.result)[0].c[0]
} catch (err) {
console.log(err)
}
}
return (
// your code for ui
)
}
// Start component
const Start = () => {
// code ...
return (
<div className='Start'>
<Switch>
<Route path={`${match.path}/:currencyId`}>
test
</Route>
<Route path={match.path}>
<Container className="cc-container">
<Row>
<Table hover className="cc-table">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Price</th>
<th>24h %</th>
<th>7d %</th>
<th>Market Cap</th>
<th>Volume (24h)</th>
<th>Circulating Supply</th>
<th>Last 30 Days</th>
</tr>
</thead>
{currencies &&
currencies.map((item, index) =>
<tbody>
<tr>
<td>{index + 1}</td>
<td><Image src={item.logo} width="38" roundedCircle /> {item.name}</td>
{ /* <td>{item.pairs}</td> HERE I WANT TO FETCH DATA */ }
<td><PriceInformation ticker={item.pairs}/></td>
</tr>
</tbody>
)
}
</Table>
</Row>
</Container>
</Route>
</Switch>
</div>
)
}

Error handling while api limit exceeds in ReactJS

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>

Filter method on another method?

I want to run a filter method on the renderTable method that I've defined below. Is it possible to do:
renderTable().filter(x => x.name)?
Right now, I have a table with rows of each category and their results from a url that provided some json data.
I would like to make a feature that allows users to adjust the setting to return their desired results.
CODE
const renderTable = () => {
return players.map(player => {
return (
<tr>
<td>{player.name}</td>
<td>{player.age}</td>
<td>{player.gender}</td>
<td>{player.state}</td>
<td>{player.status}</td>
</tr>
)
})
}
return (
<div className = "App">
<h1>Players</h1>
<table id = "players">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Gender</th>
<th>State</th>
<th>Status</th>
</tr>
</thead>
<tbody>{renderTable()}</tbody>
</table>
</div>
);
You can apply the filter before the map. Here, give this a try:
const renderTable = () => {
return players
.filter(player => player.state === "NSW")
.map(player => {
return (
<tr>
<td>{player.name}</td>
<td>{player.age}</td>
<td>{player.gender}</td>
<td>{player.state}</td>
<td>{player.status}</td>
</tr>
);
});
};
Here's a Working Sample CodeSandbox for your ref.
Yes you can. Just filter before map players.filters(...).map. But this is better
const renderTable = () => {
const rows = []
players.forEach((player, index) => {
if(player.name) {
rows.push(
<tr key={index}>
<td>{player.name}</td>
<td>{player.age}</td>
<td>{player.gender}</td>
<td>{player.state}</td>
<td>{player.status}</td>
</tr>
)
}
})
return rows;
}

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