Not able to manipulate map functions in react JS - javascript

I am trying to hit an api available at covid19 api [ you can see directly , click it ] but I am not able to map through the state.
I tried browsing the questions and still didn't find it .
my code in app.js is
import React, { Component } from 'react'
import api from '../api/covidapi'
import SearchBar from './SearchBar'
class App extends Component {
constructor(props) {
super(props);
this.state = {
country : 'Please Enter the country',
active_cases : 'No country found',
countries : [],
errorMessage : '',
isLoading : false,
};
}
async componentDidMount() {
const response = await api.get('/summary');
console.log('data loaded = > ', response);
console.log(response.data.Countries.length) // giving 247
console.log('countries ', response.data.Countries) //lists all countries {....},{...}...
this.setState({countries:response.data.Countries})
// console.log('global end')
this.setState({
totalConfirmed : response.data.Global.TotalConfirmed,
})
} //component did mount ended.
onSearchSubmit = async (country) =>{
console.log(country)
try {
const response =
await api.get(`/live/country/${country}/status/confirmed`)
this.setState({country:country, active_cases:response.data[6].Active})
}
catch(e) {
this.setState({errorMessage : "Country Doesn't exist or misspelled"})
}
}; //onsearch submit ended.
render() {
return (
<div>
<div className="container">
<p style={{textAlign:'center',
backgroundColor:'green',
color:'white',
width:'97%',margin:'auto',
padding:'24px',
marginTop:'12px',}}>
Total confirmed as of now is <span> : </span>
<span style={{color : 'red'}} >
{this.state.totalConfirmed}
</span>
</p>
<SearchBar onSubmit = {this.onSearchSubmit}/>
</div>
<div className="container">
<h2 className="bg bg-primary" style={{marginBottom:'0px',
textAlign:'center',marginTop:'15px',
padding:'10px'}}>Covid19 Cases In single Country
</h2>
<table className="table table-striped">
<thead>
<tr>
<th>Country</th>
<th>Acitve Cases</th>
</tr>
</thead>
<tbody>
<tr>
<td>{this.state.country}</td>
<td>{ this.state.active_cases}</td>
</tr>
</tbody>
</table>
</div>
<br />
<hr />
<div className="container">
<div style={{textAlign:'center',color:'red',fontWeight:'bold'}}>
</div>
<h2 className="bg bg-primary" style={{marginBottom:'0px',
textAlign:'center', padding:'10px'}}>
Covid19 Cases Worldwide
</h2>
<table className="table table-striped table-hover table-dark">
<thead>
<tr>
<th>S.N</th>
<th>Country Name</th>
<th>Confirmed Cases</th>
<th> Total Deaths</th>
<th>Total Recovered</th>
</tr>
</thead>
<tbody>
{
Object.keys(this.state.countries).map((country) => (
<tr>
<td>{country}</td>
<td>........</td>
<td>........</td>
<td> ........</td>
<td>............</td>
</tr>
))
}
</tbody>
</table>
</div>
</div>
);
}
}
export default App;
and covidapi.js code is
import axios from 'axios'
export default axios.create({
baseURL :'https://api.covid19api.com'
})
The problem is in this section of the code in app.js
{
Object.keys(this.state.countries).map((country) => (
<tr>
<td>{country}</td>
<td>........</td>
<td>........</td>
<td> ........</td>
<td>............</td>
</tr>
))
}
I am not able to map through countries in my state , I think there is
problem with the Objects and array.
when Render the country that is passed in map it return the integer value like 1,2,3 .... and not able to get other values.
Response in the console looks like this
What I am trying is to display the all the countries list to the table whenever the application loads.

You can use this.state.countries directly without Object.keys() (It is an array already), and use the properties inside each item as follows:
{
this.state.contries.map(item => {
return(
<tr>
<td> { item.Country } </td>
<td> { item.totalConfirmed } </td>
... // Other tds
</tr>
)
}
}

Related

Infinite scroll render in ReactJS with React-List using table takes too long

I want to render large lists of data inside a table. I am using the React-List library found online, but when the user scrolls about 200 items, the rest of them take too much time to load.
I achieved something like this:
After about 200 items, I get these warnings in the console, and the list starts to render slower and slower like in the image below:
I use React-List for rendering this table and a get request to get all the data once, code will be shown below.
import React from 'react';
import axios from 'axios';
import { toastr } from '../../../components/toastr/toastr.component';
import { Table } from 'react-bootstrap';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faTrashAlt } from '#fortawesome/free-solid-svg-icons';
import DaysJS from 'react-dayjs';
import Loading from '../../../components/loading/loading.component';
import Tooltip from '../../../components/tooltip/tooltip.component';
import ReactList from 'react-list';
import './error.styles.scss';
class ErrorPage extends React.Component {
constructor() {
super();
this.state = {
pending: true,
errors: []
}
};
componentDidMount() {
axios.get('/api/logError').then(resp => {
this.setState({ pending: false, errors: resp.data });
}).catch(() => toastr('error', 'Eroare la preluarea datelor!'));
};
renderItem = (index, key) => {
return (
<tr key={key}>
<td>
{this.state.errors[index].id}
</td>
</tr>
)
};
renderTable (items, ref) {
return (
<div style={{maxHeight: '400px', overflowY: 'scroll'}}>
<Table bordered striped hover size="sm">
<tbody ref={ref}>
{items}
</tbody>
</Table>
</div>
);
}
renderRow = (index, key) => {
const entry = this.state.errors[index]
return (
<tr key={key}>
<td width='40px' className='text-center'>{index}</td>
<td width='40px' className='text-center'>{entry.id_user}</td>
<td width='200px'>{entry.email}</td>
<td width='200px'>{entry.name}</td>
<td width='200px'>{entry.action}</td>
<td>{entry.error}</td>
<td width='120px' className='text-center'><DaysJS format='DD.MM.YYYY - HH:MM'>{entry.createdAt}</DaysJS></td>
<td width='30px' className='cursor-pointer text-center' data-tip data-for='tooltip'>
<Tooltip id='tooltip' message='Șterge eroare'/>
<FontAwesomeIcon className='text-danger' icon={faTrashAlt} />
</td>
</tr>
);
}
render() {
const { pending, errors } = this.state;
return (
<div className='error-page mt-3 row'>
<Loading pending={pending} />
<div className='col-sm-4 fw-bold'>Total erori: {errors.length}</div>
<div className='col-sm-4'>
<h4 className='text-center'>Erori</h4>
</div>
<div className='col-sm-4 text-end'>
<button className='btn btn-danger btn-sm'>
<FontAwesomeIcon icon={faTrashAlt} className='me-1' />
Șterge toate
</button>
</div>
<div className='col-sm-12'>
<Table bordered size="sm">
<thead>
<tr>
<th width='40px'>Id user</th>
<th width='200px'>Email</th>
<th width='200px'>Unitate</th>
<th width='200px'>Acțiune</th>
<th>Eroare</th>
<th width='120px'>Data</th>
<th width='38px'></th>
</tr>
</thead>
</Table>
<ReactList
itemsRenderer={(items, ref) => this.renderTable(items, ref)}
itemRenderer={this.renderRow}
length={errors.length}
/>
</div>
</div>
);
};
};
export default ErrorPage;
I used in AngularJS a library called ng-infinite-scroll that rendered the items with no problem with infinite scroll and I tried to find something similar for ReactJS.

if ternario does not work, function has value but never used says

I am new with programing and I want to use if ternario, but it doesn't work. I have two functions and I create a third function to show one of them or the other. It is an application in ReactJS. Below is the code:
import { Table } from "react-bootstrap";
import { Link } from "react-router-dom";
import { useCartContext } from "../../Context/CartContext";
const emptyCart = () => {
return(
<>
<div>
<h3>The Cart is empty</h3>
<p>
Return to home to see our products
</p>
<Link to='/' ><button className="btn btn-info"> Home </button></Link>
</div>
</>
);
};
const CartFunction = () => {
const { list, totalPrice } = useCartContext();
return (
<Table striped hover>
<thead>
<tr>
<th>Product</th>
<th>Title</th>
<th>Quantity</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{list.map((varietal) => (
<tr key={varietal.id}>
<td>
<img
src={varietal.pictureUrl}
alt='img'
style={{ width: "82px" }}
/>
</td>
<td>{varietal.title}</td>
<td>{varietal.count}</td>
<td>${varietal.price}</td>
</tr>
))}
</tbody>
<thead>
<tr>
<td colSpan="3">Total</td>
<td>${totalPrice()}</td>
</tr>
</thead>
</Table>
);
};
const CartComponent = () => {
const { list } = useCartContext();
return (
<>
{list.length !== 0 ? <CartFunction /> : <emptyCart />}
</>
);
};
export default CartComponent;
Visual Code it says that emptyCard has a value but it is never used. If there is someone that could help me I would appreciate it. Cheers

React don't render a map function of an Axios call

I'm trying to make a shopping cart table in which it shows an image, name of the product and a remove button. I've the id of each product from the localStorage and call all the data of that id with Axios.get(by id).
I'd created a table to show the price, image and name of the product, but my .map function don't show the info in the website (even though I can see it with a console.log). Here is the code:
import Axios from "axios";
import React from "react";
function ClientCardBlock() {
let memory = window.JSON.parse(localStorage.getItem("toy"));
console.log(memory); **this log shows me that all the IDs are now in an array**
const renderItems = () => {
memory.map(
async (toy_id) =>
await Axios.get(`http://************/${toy_id}`).then(
(response) => {
const toy = response.data;
console.log(toy.price); **this log show me the price of each toy, so it's working**
return (
<tr key={toy._id}>
<th>
<img
alt=""
className="card-img-top embed-responsive-item"
src={`http://*********/${toy.images}`}
/>
</th>
<th>$ {toy.price}</th>
<th>
<button>Remove</button>
</th>
</tr>
);
}
)
);
};
return (
<div>
<table className="table table-bordered">
<thead>
<tr>
<th scope="col">Image product</th>
<th scope="col">Product</th>
<th scope="col">Remove</th>
</tr>
</thead>
<thead>{renderItems()}</thead>
</table>
</div>
);
}
export default ClientCardBlock;
Normally you'd be able to just change it so that renderItems is a functional component.
function RenderItems() {
return memory.map...(etc)
}
...
<thead><RenderItems /></thead>
but since this is an async function, you need to use a useEffect. This useEffect gets the data and saves it into your component state. Then once it exists, it will render later. The key point is to seperate the fetching from the rendering.
function ClientCardBlock() {
const [data, setData] = useState([]);
useEffect(() => {
/* this runs on component mount */
const memory = window.JSON.parse(localStorage.getItem("toy"));
Promise.all(memory.map((toy_id) => Axios
.get(`http://************/${toy_id}`)
.then((response) => response.data)))
/* Wait on the Promise.All */
.then(newData => {
/* Set the data locally */
setData(newData);
});
}, []);
return (
<div>
<table className="table table-bordered">
<thead>
<tr>
<th scope="col">Image product</th>
<th scope="col">Product</th>
<th scope="col">Remove</th>
</tr>
</thead>
<thead>
{data.map(toy => (
<tr key={toy._id}>
<th>
<img
alt=""
className="card-img-top embed-responsive-item"
src={`http://*********/${toy.images}`}
/>
</th>
<th>$ {toy.price}</th>
<th>
<button>Remove</button>
</th>
</tr>
)}
</thead>
</table>
</div>
);
}
export default ClientCardBlock;

How can i display key value pairs in a table grid in react js.?

I'm trying to display key-value pairs in react js,
but somehow I cannot display them properly. I have created a table widget and I am not getting the right display
My table Widget
import React from "react";
function Table(props) {
const { tablevalue } = props;
console.log(tablevalue);
return (
<div className="table">
<table className="table table-hover">
<tbody>
{tablevalue.map((item, value) =>
Object.entries(item, (key, value) => {
return (
<tr className="table-row">
<th scope="col" key={`tablevalue-${key}`}>
{key}
</th>
<td key={`tablevalue-${value}`}>{value}</td>
</tr>
);
})
)}
</tbody>
</table>
</div>
);
}
export default Table;
app.js
import React, { Fragment } from "react";
import Dropdown from './components/widgets/Dropdown/index'
import Table from './components/widgets/Table/index'
function DropdownTest() {
return (
<h3>
<b>Profit</b>
</h3>
<br />
<Table
tablevalue = {[{key:'Binance' , value: 'Polonix'}, {key:'Profit' , value:'Loss'}]}
/>
</div>
);
}
export default DropdownTest;
My output
Whereas I want my output to be displayed in terms of table
You can use table header
<tbody>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
{tablevalue.map(({ key, value }) => (
<tr className="table-row">
<td key={`tablevalue-${key}`}>{key}</td>
<td key={`tablevalue-${value}`}>{value}</td>
</tr>
))}
</tbody>
Code
const Table = ({ tablevalue }) => (
<div className="table">
<table className="table table-hover">
<tbody>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
{tablevalue.map(({ key, value }) => (
<tr className="table-row">
<td key={`tablevalue-${key}`}>{key}</td>
<td key={`tablevalue-${value}`}>{value}</td>
</tr>
))}
</tbody>
</table>
</div>
);
const DropdownTest = () => (
<div>
<h3>
<b>Profit</b>
</h3>
<br />
<Table
tablevalue={[
{ key: "Binance", value: "Polonix" },
{ key: "Profit", value: "Loss" }
]}
/>
</div>
);
ReactDOM.render(
<React.StrictMode>
<DropdownTest />
</React.StrictMode>,
document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I've not seen Object.entries used this way. I would usually use a forEach on it:
Object.entries(item).forEach(entry => {
let key = entry[0];
let value = entry[1];
});
Though a little bit more performant would be using a for in instead, as Object.entries creates a brand new array then forEach iterates through that, which is unnecessary:
for (const key in item) {
let value = obj[key];
}
You can do it this way:
import React from "react";
export default props => {
console.log(props.tablevalue);
const ths = props.tablevalue.map(({ key, value }) => (
<th key={value}>{key}</th>
));
const values = props.tablevalue.map(obj => <td>{obj.value}</td>);
return (
<>
<table>
<tr>{ths}</tr>
<tr>{values}</tr>
</table>
</>
);
};
Here's a stackblitz that displays the table.
Ultimately it all comes down to how you want that table to be displayed, you can tweak some things as you want.
I think you have to create a header separately. and after that loop thought the data and apply css for table row. please find the below code.
import React from 'react';
import './index.css';
function Table(props) {
const {
tablevalue,
} = props
console.log(tablevalue)
return (
<div className="table">
<table className="table table-hover">
<tbody>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
{tablevalue.map((item, value) => {
return (
<tr className="table-row">
<td key={`tablevalue-${value}`}>{item.key}</td>
<td key={`tablevalue-${value}`}>{item.value}</td>
</tr>
)
})}
</tbody>
</table>
</div>
)
}
export default Table;
Check this sandbox: https://codesandbox.io/s/goofy-breeze-fdcdr
Object.keys(tablevalue[0]).map((key) => {key}). You can use this in header tr and loop over it then
Change the Table component to something like this:
import React from "react";
function Table(props) {
const { tablevalue } = props;
return (
<div className="table">
<table className="table table-hover">
<tbody>
<tr>
{Object.keys(tablevalue[0]).map(key => (
<th key={key}>{key}</th>
))}
</tr>
{tablevalue.map(({ key, value }) => (
<tr className="table-row" key={`tablevalue-${key}`}>
<td>{key}</td>
<td>{value}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
export default Table;

React - View doesn't update after setState

I am working on a React component since a long time but for some reason my view doesn't update after doing an ajax call and setting a state.
So, basically, I have a state of clients which is at the beginning an empty array. In the lifecycle method componentDidMount I do an ajax call and in the .then promise I set the state to the response. But for some reason, the view doesn't get updated since the p tag saying "there are no clients" still is there, and a map function I wrote doesn't output any results.
I am sure the clients state is updated since I console.log the result after setting the state and Also in my React dev tools I can see that the clients state has 1 item.
For context, I am using this component in a Laravel project but that doesn't make any difference I guess.
My code
import React, { Component } from 'react';
class Clients extends Component {
constructor(props) {
super(props);
this.state = {
clients: [],
};
}
componentDidMount() {
this.getClients();
}
getClients() {
axios.get('/oauth/clients')
.then(({data}) => {
this.setState({
clients: data,
}, () => {
console.log(this.state.clients);
});
});
}
render() {
const clients = this.state.clients;
return (
<div>
{/* Begin card */}
<div className="card card-default">
<div className="card-header">
<div style={flex}>
<span>
OAuth Clients
</span>
{/* <a class="action-link" tabindex="-1" #click="showCreateClientForm"> */}
<a className="action-link" tabIndex="-1">
Create New Client
</a>
</div>
</div>
<div className="card-body">
{ clients.length === 0 &&
<p className="mb-0">
You have not created any OAuth clients.
</p>
}
<table className="table table-borderless mb-0">
<thead>
<tr>
<th>Client ID</th>
<th>Name</th>
<th>Secret</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{ clients.map(client => {
return (
<tr key={client.id}>
<td style={alignMiddle}>
{client.id}
</td>
<td style={alignMiddle}>
{client.name}
</td>
<td style={alignMiddle}>
{client.secret}
</td>
<td style={alignMiddle}>
<a className="action-link" tabIndex="-1">
Edit
</a>
</td>
<td style={alignMiddle}>
<a className="action-link text-danger">
Delete
</a>
</td>
</tr>
);
}) }
</tbody>
</table>
</div>
</div>
{/* End card */}
</div>
);
}
}
// Styles
const flex = {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
};
const alignMiddle = {
verticalAlign: 'middle',
};
export default Clients;
Am I missing something?

Categories

Resources