Why does my component mount twice after fetching data from API? - javascript

TableHeader and TableBody component render twice after fetching data from API due to Table row are rendered twice and given duplicate key error in Reactjs.
Error : Each child in a list should have a unique "key" prop.
enter image description here
class Table extends React.Component {
state = {
headers: [],
accesors: [],
data: [],
loading: true
};
componentDidMount() {
instance.get('UserRole/GetDataList')
.then(response => {
var data = JSON.parse(response.data);
this.setState({
headers: Object.keys(data[0]),
data: data,
loading: false
}, () => this.setAccesors());
}, error => {
console.log(error);
});
}
render() {
const { headers, accesors, data } = this.state;
if (this.state.loading ) {
return "Loading...."
}
else {
return (
<table id="datatable-responsive" className="table table-
striped table-bordered">
<TableHeader headers={headers} />
<TableBody data={data} />
</table>
);
}
}
}
export default Table;

Related

Not getting data from api into the web page, can anyone help me through this where I am getting an error and what can i do to get data

import React from 'react';
/**
App
Simple react js fetch example
*/
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
isLoaded: false
}
}
/**
componentDidMount
Fetch json array of objects from given url and update state.
*/
componentDidMount() {
fetch('https://run.mocky.io/v3/8260aa5d-8af8-4cff-999e-6e81b217f0ba')
.then(res => res.json())
.then(json => {
this.setState({
items: json,
isLoaded: true,
})
}).catch((err) => {
console.log(err);
});
}
/**
render
Render UI
*/
render() {
const { isLoaded, items } = this.state;
if (!isLoaded)
return Loading...;
return (
{items.map(item => (
Name: {item.name}
))}
);
}
}
export default App;
in render function
return (
{
items.clients.map(item => (<span key={item.id}> Name : {item.name}
</span>)
)
}
)

TypeError: this.state.data.map in reactjs

class Home extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoaded: false,
};
}
componentDidMount() {
fetch("https://reqres.in/api/users?page=2")
.then((res) => res.json())
.then((json) => {
this.setState({
isLoaded: true,
data: json,
});
});
}
render() {
var { isLoaded, data }= this.state;
if(!isLoaded){
return<div>Is isLoaded</div>
}
else{
return (
<div>
<ul>
{() =>
this.state.data.map((data, index) => (
<li key={index}>Email: {data.email}</li>
))
}
;
</ul>
</div>
);
}
}
}
export default Home;
Hii All , I know this question is asked many times but I cant figure it out I'am getting the error. I have checked for all the questions similar to this but haven't found specific solution if I use another link i.e, "https://jsonplaceholder.typicode.com/users" this one the code works fine .
The returned data from https://reqres.in/api/users?page=2 is not an array, but an object with a data property containing what you are looking for (an array). The result of the request is :
{"page":1,"per_page":6,"total":12,"total_pages":2,"data":[{"id":1,"email":"george.bluth#reqres.in","first_name":"George","last_name":"Bluth","avatar":"https://reqres.in/img/faces/1-image.jpg"},{"id":2,"email":"janet.weaver#reqres.in","first_name":"Janet","last_name":"Weaver","avatar":"https://reqres.in/img/faces/2-image.jpg"},{"id":3,"email":"emma.wong#reqres.in","first_name":"Emma","last_name":"Wong","avatar":"https://reqres.in/img/faces/3-image.jpg"},{"id":4,"email":"eve.holt#reqres.in","first_name":"Eve","last_name":"Holt","avatar":"https://reqres.in/img/faces/4-image.jpg"},{"id":5,"email":"charles.morris#reqres.in","first_name":"Charles","last_name":"Morris","avatar":"https://reqres.in/img/faces/5-image.jpg"},{"id":6,"email":"tracey.ramos#reqres.in","first_name":"Tracey","last_name":"Ramos","avatar":"https://reqres.in/img/faces/6-image.jpg"}],"support":{"url":"https://reqres.in/#support-heading","text":"To keep ReqRes free, contributions towards server costs are appreciated!"}}
So you cannot use map function, which is from the Array prototype, on the result of your request. You must access the data property first :
this.state.data.data.map((data, index) => ( // note the double data
<li key={index}>Email: {data.email}</li>
))
You could also assign json.data to the state.data to avoid the ugly .data.data :
this.setState({
isLoaded: true,
data: json.data, // note the .data
});
I think the problem is in brackets around your .map() method. Please try this
class Home extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoaded: false,
};
}
componentDidMount() {
fetch("https://reqres.in/api/users?page=2")
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
data: json,
});
});
}
render() {
const { isLoaded, data } = this.state;
if (!isLoaded) {
return <div>Is isLoaded</div>;
} else {
return (
<div>
<ul>
{data?.map((data, index) => {
return <li key={index}>Email: {data.email}</li>;
})}
</ul>
</div>
);
}
}
}
export default Home;
I don't see any error, it's working just fine.
Output:
Working Example: StackBlitz
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoaded: false,
};
}
componentDidMount() {
fetch('https://reqres.in/api/users?page=2')
.then((res) => res.json())
.then((json) => {
console.log(json.data);
this.setState({
isLoaded: true,
data: json.data,
email: null,
});
});
}
render() {
var { isLoaded, data } = this.state;
if (!isLoaded) {
return <div>Is isLoaded</div>;
} else {
return (
<div>
<div className="contents home">
<img
src="https://trucard.io/india/wp-content/uploads/2021/08/2021-June-TruCard-Logo.png
"
width={50}
alt="img"
className="trucard-img"
/>
</div>
<div className="button">
<button className="button-button">Load list</button>
</div>
<ul>
{this.state.data?.map((data, index) => (
<li key={index}>Email: {data.email}</li>
))}
;
</ul>
</div>
);
}
}
}
export default App;

Reactjs - Re render data on button click

I am using an API to fetch some data. When the page loads it fetches some random data, but I want to allow the user to sort the data by clicking a button. I have made a function to sort these data from the API I am using. What I want to do now is: When the button to sort data is clicked, I want the new data to be replaced with the old data.
Here is my current code:
class Data extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
offset: 0, perPage: 12 // ignore these two
};
}
// The random data that I want to be displayed on page load
receivedData() {
axios
.get(`https://corona.lmao.ninja/v2/jhucsse`)
.then(res => {
const data = res.data;
const slice = data.slice(this.state.offset, this.state.offset + this.state.perPage) // ignore this
const postData = slice.map(item =>
<tr key={Math.random()}>
<td>{item.province}, {item.country}</td>
<td>{item.stats.confirmed}</td>
<td>{item.stats.deaths}</td>
<td>{item.stats.recovered}</td>
</tr>
)
this.setState({
pageCount: Math.ceil(data.length / this.state.perPage), // ignore this
postData
})
});
}
// The data to be sorted when the "country" on the table head is clicked
sortData() {
axios
.get(`https://corona.lmao.ninja/v2/jhucsse`)
.then(res => {
const data = res.data;
var someArray = data;
function generateSortFn(prop, reverse) {
return function (a, b) {
if (a[prop] < b[prop])
return reverse ? 1 : -1;
if (a[prop] > b[prop])
return reverse ? -1 : 1;
return 0;
};
}
// someArray.sort(generateSortFn('province', true))
const tableHead = <tr>
<th onClick={() => someArray.sort(generateSortFn('province', true))}>Country</th>
<th>Confirmed Cases</th>
<th>Deaths</th>
<th>Recovered</th>
</tr>
this.setState({
tableHead
})
});
}
componentDidMount() {
this.receivedData()
this.sortData() // This function should be called on the "Country - table head" click
}
render() {
return (
<div>
<table>
<tbody>
{this.state.tableHead}
{this.state.postData}
</tbody>
</table>
</div>
)
}
}
export default Data;
Think a litte bit different. In the componentDidMount get you're Data in some form. Set it with setState only the raw Data not the html. Then resort the data on button click. React rerenders if the state changes automatically
class Data extends React.Component {
constructor(props) {
super(props);
this.state = {
data
}
}
getData() {
fetchData('url').then(res) {
this.setState({data: res.data})
}
}
componentDidMount() {
this.getData()
}
sort() {
let newSorted = this.state.data.sort //do the sorting here
this.setState({data: newSorted})
}
render() {
return() {
<table>
<tablehead><button onClick={this.sort.bind(this)}/></tablehead>
{this.state.data.map(data => {
return <tablecell>{data.name}</tablecell>
})}
</table>
}
}
}

Send array of objects to render in React

Having an array of this form:
[{"game_id":4,"city":"London","year":2018,"athlete_id":"1"},
{"game_id":2,"city":"Paris","year":2016,"athlete_id":"2"}]
it is received from back-end and stored like this:
callAPI() {
fetch('http://localhost:9000/testAPI')
.then((res) => res.text())
.then((res) => this.setState({ apiResponse: res }));
}
and then, in the render is send as props to the Table component:
render() {
return (
<div className='App'>
<header className='App-header'>
<Table data={this.state.apiResponse} />
</header>
</div>
);
}
The problem comes here when I want to send to the table only parts of apiResponse.
This is the component:
class Table extends React.Component {
constructor(props) {
super(props);
}
getGames = function () {
return this.props.data;
};
render() {
return (
<div>
<table>
<thead>
<tr>{this.getGames()}</tr>
</thead>
</table>
</div>
);
}
}
The above code sends all the data, so I tried to send only the data that I want, for example only the keys and make headers out of them.
So I replaces the content of getGames() with this:
getGames = function () {
return Object.keys(this.props.data[0]);
};
but it throws this error:
TypeError: Cannot convert undefined or null to object
What I want is to create a table with headers: game_id, city, year, athelete_id and their columns the show their corresponding data.

Datatable functions are not working with Reactjs

I'm using Datatable Library to draw table easily.
And I got a data with Fetch API and render to table and It works well. But I don't know why DataTable Funcions like sorting, searching, showing options.
As you see, get data from API and render to HTML are works well, but when I click sort or search function it changes to this.
Also Another functions like interval the data from API every 10 seconds and render to table are works well.
It seems that there are some problem in initial state.
import React, { Component } from 'react';
import './PostContainer.css';
class PostContainer extends Component {
constructor(props) {
super(props);
this.state = {
tableData: {
status: '0000',
data: {
loading: { sell_price: 'loading', volume_7day: 'loading' },
},
},
};
}
async componentDidMount() {
this.getData();
this.interval = setInterval(() => {
this.getData();
}, 10000);
}
getData() {
fetch('https://api.bithumb.com/public/ticker/all')
.then(res => {
const data = res.json();
return data;
})
.then(res => {
this.setState({
tableData: res,
});
})
.catch(error => {
console.error(error);
});
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
let data = this.state.tableData;
let chart = [];
console.log(data);
if (data.status === '0000') {
delete data.data['date'];
for (let [key, value] of Object.entries(data.data)) {
chart.push(
<tr key={key}>
<td>{key}</td>
<td>{value.sell_price}</td>
<td>{value.volume_7day}</td>
</tr>
);
}
} else if (
data.status === '5500' ||
data.status === '5600' ||
data.status === '5900'
) {
this.setState({
tableData: {
data: {
ERROR: {
sell_price: 'ERROR with API',
volume_7day: 'ERROR with API',
},
},
},
});
}
return (
<div className="Post">
<table id="table" className="table table-striped table-bordered">
<thead>
<tr>
<th>Coin Name</th>
<th>Current Price</th>
<th>Volume</th>
</tr>
</thead>
<tbody>{chart}</tbody>
</table>
</div>
);
}
}
export default PostContainer;
Can access to DEMO directly. I uploaded to Github Pages.
I can think of 2 issue to look for
a.
If you see in screenshot there is no Pagination.
When I try load DEMO with Developer Console open.
It works fine and you will see Pagination which will show 10 record at a time.
Check your code for Datatable initialization code in index.js
$('#table').DataTable({
order: [[1, 'desc']],
});
Make sure above code is called after Data is loaded in HTML
b.
Your state value is not updated to actual values while sorting
tableData: {
status: "0000",
data: {
loading: {
sell_price: "loading",
volume_7day: "loading"
}
}
}

Categories

Resources