How To Conditional Render Data From 2 Data Sources Using React - reactjs

I am rendering data from two JSON files in react. First file is my main file and from the second file I want conditional rendering on the basis of the first file.
Explanation: From First file name "maindata.json" I am rendering all the data into a table. There is a Unique id field in the Json in first file. From Second file I just want to populate only a date fieldand there is also a unique id in the second JSON. What I want is if the main JSon file id matches with the id in the second json file, so print the date from the second file in the same row next to the id from the main file.
What I have done.
I have applied the condition but the problem is its not doing the match and prints all the dates in one column.
React App is getting slower ( performance Issue )
Here is my Code sample.
import React, { Component } from "react";
import "../node_modules/bootstrap/dist/css/bootstrap.min.css";
import ReactHTMLTableToExcel from 'react-html-table-to-excel';
import data from "./data/maindata.json";
import data1 from "./data/data2.json";
class PenApprovals extends Component {
render() {
return (
<div className="container-fluid" style={{ backgroundColor: '#f7f7f7' }}>
<table id="table-to-xls" className="table table-responsive table-striped display nowrap" >
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Date</th>
<th scope="col">Status</th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
{data.map((record) => (
<tr>
<td>{record.UniqueName}</td>
<td>
{data1.map((item) =>
<React.Fragment>
//Here fetching date from second file
{item.uniqueName === <span>{record.UniqueName}</span> ? <span>
{item.assignedDate}</span> : "NO Match Found" }
</React.Fragment>
)}
</td>
<td>{record.Status }</td>
<td>{record.Name}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
}
export default PenApprovals;
here is JSON Sample.
Main Data File
[
{
"UniqueName": "CR30876",
"StatusString": "Submitted",
"Name": "Pegasus Test 1"
},
{
"UniqueName": "CR35876",
"StatusString": "Submitted",
"Name": "Pegasus Test 1"
}
]
Second Conditional JSON File sample
[
{
"uniqueName": "CR35876",
"assignedDate": "2020-11-09",
},
{
"uniqueName": "CR34523",
"assignedDate": "2020-11-09",
}
//More records....
]
Thanks Everyone.

You should use filter instead of map! Here's the code that works.
class PenApprovals extends Component {
render() {
return (
<div className="container-fluid" style={{ backgroundColor: "#f7f7f7" }}>
<table
id="table-to-xls"
className="table table-responsive table-striped display nowrap"
>
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Date</th>
<th scope="col">Status</th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
{data.map((record) => {
const tgt = data1.filter(
(item) => item.uniqueName === record.UniqueName
);
return (
<tr>
<td>{record.UniqueName}</td>
<td>
{tgt.length
? tgt.map((item) => (
<React.Fragment key={item.uniqueName}>
<span>{item.assignedDate}</span>
</React.Fragment>
))
: "NO Match Found"}
</td>
<td>{record.StatusString}</td>
<td>{record.Name}</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
}
}
export default PenApprovals;

Related

Why tankStack React-table render the td tag 2 times after defining which component should render in column

I am facing a weird problem while working with tankStack react-table. I want render some specific tags with extra data. example: i want to render the age column like this (this is the {age})
But don't want to make the tag child of tag but that is happening
Here is my code
<table>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => {
return(
<td key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
)
})
}
</tr>
))}
</tbody>
</table>
Column.js
export const COLUMNS = [
{
header:'First Name',
accessorKey:'first_name',
id:'first_name'
},
{
header:'Last Name',
accessorKey:'last_name',
id:'last_name'
},
{
header:'Age',
accessorKey:'age',
id:'age',
cell: data => <td>this is age{data.getValue()}</td>,
enableGlobalFilter: false,
}
]

Each child in a list should have a unique "key" prop Error in React

Hi I am currently working with Spotify API with Spring Boot as the backend and React for the front end.
I was able to retrieve a user's favorite artist using the API in a json format but as I am not familiar with React, I am currently having problems displaying the data.
The json data that I have retrieved looks something like this.
[{"externalUrls":{"externalUrls":{"spotify":"https://open.spotify.com/artist/3dz0NnIZhtKKeXZxLOxCam"}},"followers":{"href":null,"total":929384},"genres":["complextro","edm","progressive electro house"],"href":"https://api.spotify.com/v1/artists/3dz0NnIZhtKKeXZxLOxCam","id":"3dz0NnIZhtKKeXZxLOxCam","images":[{"height":640,"url":"https://i.scdn.co/image/ab6761610000e5eb1804f56bdcb9322c5f3f8f21","width":640},{"height":320,"url":"https://i.scdn.co/image/ab676161000051741804f56bdcb9322c5f3f8f21","width":320},{"height":160,"url":"https://i.scdn.co/image/ab6761610000f1781804f56bdcb9322c5f3f8f21","width":160}],"name":"Porter Robinson","popularity":68,"type":"ARTIST","uri":"spotify:artist:3dz0NnIZhtKKeXZxLOxCam"},{"externalUrls":{"externalUrls":{"spotify":"https://open.spotify.com/artist/6M2wZ9GZgrQXHCFfjv46we"}},"followers":{"href":null,"total":27618208},"genres":["dance pop","pop","uk pop"],"href":"https://api.spotify.com/v1/artists/6M2wZ9GZgrQXHCFfjv46we","id":"6M2wZ9GZgrQXHCFfjv46we","images":[{"height":640,"url":"https://i.scdn.co/image/ab6761610000e5ebd42a27db3286b58553da8858","width":640},{"height":320,"url":"https://i.scdn.co/image/ab67616100005174d42a27db3286b58553da8858","width":320},{"height":160,"url":"https://i.scdn.co/image/ab6761610000f178d42a27db3286b58553da8858","width":160}],"name":"Dua Lipa","popularity":94,"type":"ARTIST","uri":"spotify:artist:6M2wZ9GZgrQXHCFfjv46we"}]
I am hoping to display this with React but seem to run into an error that reads
"Warning: Each child in a list should have a unique "key" prop."
My 'ListArtistComponent.jsx' file in my React application looks something like this.
class ListArtistComponent extends Component{
constructor(props) {
super(props);
this.state = {
artist: []
}
}
componentDidMount(){
ArtistService.getArtist().then((res) => {
this.setState({ artist: Array.from(res.data)});
});
}
render() {
return(
<div>
<h2 className="text-center">Artist List</h2>
<div className="row">
<table className="table table-striped table-bordered">
<thead>
<tr>
<th>Artist Name</th>
<th>Artist Popularity</th>
</tr>
</thead>
<tbody>
{
this.state.artist.map(
artist =>
<tr key = {artist.id}>
<td> {artist.name} </td>
<td> {artist.popularity} </td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
)
}
}
export default ListArtistComponent;
And my ArtistService looks something like this
class ArtistService {
getArtist(){
return axios.get("http://localhost:8080/api/topartist")
}
}
export default new ArtistService()
I am guessing that a problem occurred when setting the 'id'(in the given json "3dz0NnIZhtKKeXZxLOxCam" and "6M2wZ9GZgrQXHCFfjv46we" respectively) value as the key, it would be appreciated if I could know what seems to be causing the problem and a solution for it.
Thank you in advance!!
I don't see any problem.
But if we use array index for the unique key.
can you try this?
class ListArtistComponent extends Component{
constructor(props) {
super(props);
this.state = {
artist: []
}
}
componentDidMount(){
ArtistService.getArtist().then((res) => {
this.setState({ artist: Array.from(res.data)});
});
}
render() {
return(
<div>
<h2 className="text-center">Artist List</h2>
<div className="row">
<table className="table table-striped table-bordered">
<thead>
<tr>
<th>Artist Name</th>
<th>Artist Popularity</th>
</tr>
</thead>
<tbody>
{
this.state.artist.map(
(artist,index) =>
<tr key = {index}>
<td> {artist.name} </td>
<td> {artist.popularity} </td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
)
}

Problem in implementing search filter in data tables in react

I am implementing a search filter feature in my react data table. You can see the UI here for a better understanding of code.
I implemented it to search the data by names initially. (I will implement it to search in all columns later). It seems that the filter search isn't working. I am new to react and I did everything correct upto my Knowledge but I am still missing something.
Here is my Bookings2.js (Table is implemented in this)
import React, {useState, useEffect} from 'react';
import axios from 'axios';
import {Link} from 'react-router-dom';
import '../../static/Bookings.css';
import {BsFilterRight} from "react-icons/bs";
const Bookings2= ()=>{
const[Bookings, setBooking]=useState([]);
const[search, setSearch]=useState("");
useEffect(()=>{
loadUsers();
}, []);
useEffect(()=>{
setBooking(
Bookings.filter(Booking=>{
return Booking.name.toLowerCase().includes(Booking.name.toLowerCase())
})
)
}, [search, Bookings]);
const loadUsers= async()=>{
const result =await axios.get("http://localhost:3001/Bookings");
setBooking(result.data.reverse());
};
const deleteUser=async id => {
await axios.delete(`http://localhost:3001/Bookings/${id}`);
loadUsers();
}
return(
<div className="Booking-page-container">
<h2 className="text-center mb-4">Bookings2 Page</h2>
<table class="table table-bordered table-striped border shadow">
<thead>
<tr>
<th scope="col" colSpan={5}>
<BsFilterRight/>
<input
placeholder=" search....."
onChange={e=>setSearch(e.target.value)}
/>
</th>
</tr>
</thead>
<thead class="thead-dark">
<tr>
<th scope="col"></th>
<th scope="col">Name</th>
<th scope="col">Consultant</th>
<th scope="col">Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{Bookings.map((Booking,index)=>(
<tr>
<th scope="row">{index+1}</th>
<td>{Booking.name}</td>
<td>{Booking.consultant}</td>
<td>{Booking.email}</td>
<td>
<Link class="btn btn-primary mr-2" to={`/Bookings/view/${Booking.id}`}>View</Link>
<Link class="btn btn-outline-primary mr-2" to={`/Bookings/edit/${Booking.id}`}>Edit</Link>
<Link class="btn btn-danger" onClick={()=>deleteUser(Booking.id)}>Delete</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default Bookings2;
There may be other inconsistencies and I would be happy to work with you on those, but the first thing that stands out is this:
setBooking(
Bookings.filter(Booking=>{
return Booking.name.toLowerCase().includes(Booking.name.toLowerCase())
})
)
It should be:
if(search.length){
setBooking(
Bookings.filter(Booking =>
Booking.name.toLowerCase().includes(search.toLowerCase())
)
)
}
This assumes, of course, that your Bookings array is an array of objects that have a name key in them.
EDIT: Create a variable called bookings_array and put it outside the component:
...
let bookings_array = [];
const Bookings2= ()=>{
const[Bookings, setBooking]=useState([]);
const[search, setSearch]=useState("");
...
Then, change your loadUsers to:
const loadUsers= async()=>{
const result =await axios.get("http://localhost:3001/Bookings");
bookings_array = result.data.reverse();
setBooking(bookings_array);
};
And then change what's inside your useEffect to:
if(search.length){
setBooking(
Bookings.filter(Booking =>
Booking.name.toLowerCase().includes(search.toLowerCase())
)
)
}else{
setBooking(bookings_array)
}

Problem in implementing Search Filter in Reactjs- Trigger issues

I am implementing a react data table with a search filter in it to search the rows. You can see the UI here for a better understanding of code. I implemented it to search the rows by names initially. (I will implement it to search in all columns later).
As you can see in the UI that there are three entries at top named "Kamakshi", "Kanika" and "Kanika" respectively. When I type "Kam" in the search box then this result is shown. Now on pressing backspace my input becomes "ka", which means my search result should show three rows of "Kamakshi", "Kanika" and "Kanika". But there are no changes.
I want to trigger the search filter everytime there is a change in input. I passed it as dependency in useEffect but it didn't worked.
Here is my Bookings2.js (Table is implemented in this)
import React, {useState, useEffect} from 'react';
import axios from 'axios';
import {Link} from 'react-router-dom';
import '../../static/Bookings.css';
import {BsFilterRight} from "react-icons/bs";
let bookings_array = [];
const Bookings2= ()=>{
const[Bookings, setBooking]=useState([]);
const[search, setSearch]=useState("");
useEffect(()=>{
loadUsers();
}, []);
useEffect(()=>{
if(search.length){
setBooking(
Bookings.filter(Booking =>
Booking.name.toLowerCase().includes(search.toLowerCase())
)
)
}else{
setBooking(bookings_array)
}
}, [search, Bookings]);
const loadUsers= async()=>{
const result =await axios.get("http://localhost:3001/Bookings");
bookings_array=result.data.reverse();
setBooking(bookings_array);
};
const deleteUser=async id => {
await axios.delete(`http://localhost:3001/Bookings/${id}`);
loadUsers();
}
return(
<div className="Booking-page-container">
<h2 className="text-center mb-4">Bookings2 Page</h2>
<table class="table table-bordered table-striped border shadow">
<thead>
<tr>
<th scope="col" colSpan={5}>
<BsFilterRight/>
<input
placeholder=" search....."
onChange={e=>setSearch(e.target.value)}
/>
</th>
</tr>
</thead>
<thead class="thead-dark">
<tr>
<th scope="col"></th>
<th scope="col">Name</th>
<th scope="col">Consultant</th>
<th scope="col">Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{Bookings.map((Booking,index)=>(
<tr>
<th scope="row">{index+1}</th>
<td>{Booking.name}</td>
<td>{Booking.consultant}</td>
<td>{Booking.email}</td>
<td>
<Link class="btn btn-primary mr-2" to={`/Bookings/view/${Booking.id}`}>View</Link>
<Link class="btn btn-outline-primary mr-2" to={`/Bookings/edit/${Booking.id}`}>Edit</Link>
<Link class="btn btn-danger" onClick={()=>deleteUser(Booking.id)}>Delete</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default Bookings2;
Instead of filtering the state array, try filtering the original, which is stored in bookings_array. So change this:
if (search.length) {
setBooking(
Bookings.filter(Booking =>
Booking.name.toLowerCase().includes(search.toLowerCase())
)
)
} else {
setBooking(bookings_array)
}
to:
if (search.length) {
setBooking(
bookings_array.filter(Booking =>
Booking.name.toLowerCase().includes(search.toLowerCase())
)
)
} else {
setBooking(bookings_array)
}
Whenever a change happens in the search, you are removing things from Bookings...but you do not add them back in when new changes roll in, which is why they are not returning on a backspace. You need to run your loadUsers function again if you want to load your original Bookings back in to be filtered.

Loop through array using Map in React throw error

I have a functional component which is reading data from an API. I have defined an Interface but unable to loop and display in table using Map in react.
error
index.js:1 Warning: Each child in a list should have a unique "key" prop.
Interface
export interface ISiteManager{
managerId: number,
name: string,
isDeleted: false
}
React functional component return template
...
return (
<div>
<h2>EziTracker Dashboard Report</h2>
{eziStatusCollection && eziStatusCollection.length >0 && (
<table className="table">
<thead>
<tr>
<th>ManagerId</th>
<th>Name</th>
<th>Is Deleted</th>
</tr>
</thead>
{
eziStatusCollection.map((item, index) => {
return(
<tbody>
<tr key={index}>
<td>{item.managerId}</td>
<td>{item.name}</td>
<td>{item.isDeleted}</td>
</tr>
</tbody>
)})
}
</table>)}
</div>
);
};
export default MyComponent;
Your table body should be outside the map, as it's looping it each time as well:
<tbody>
{
eziStatusCollection.map((item, index) => {
return(
<tr key={index}>
<td>{item.managerId}</td>
<td>{item.name}</td>
<td>{item.isDeleted}</td>
</tr>
)})
}
</tbody>
This way the map key will be associated with each child (tr) and the error shouldn't occur.

Resources