I have a functional component which is reading data from an API. I have defined an Interface but unable to assign API data to Interface, followed by loop and display in table using Map in react.
Interface
export interface IEziTrackerStatus{
Schedules: EziSchedules [],
eziClient: {
clientId: number,
isActive: boolean,
name: string
}
}
..
export interface EziSchedules
{
id: number,
startTime: Date,
endTime: Date
}
component
const MyComponent = () => {
const [eziStatusCollection, setEziTrackerStatus] = useState<IEziTrackerStatus>();
useEffect(() =>{
getEziTrackerStatusReport();
},[]);
const getEziTrackerStatusReport = () =>{
(async () =>{
try{
const resp = await apiRequest(EcpApiMethod.GET, `${api.eziTrackerStatus}`, null);
setEziTrackerStatus(resp);
var x= eziStatusCollection; //HELP HERE - Undefined error
debugger;
}
catch (error) {
console.log(error);
}
})();
}
need help here
{eziStatusCollection && eziStatusCollection.eziAreaManager ????
<table className="table">
<tr>
<td>SideIt</td>
</tr>
{
eziStatusCollection.Schedules.map(item => (
<tr>
<td>{item.siteId}</td>
</tr>
))
}
Why do you have a Immediately Invoked Function Expression which is wrap getEziTrackerStatusReport method.
Define it like this,
const getEziTrackerStatusReport = async () => {
try{
const resp = await apiRequest(EcpApiMethod.GET, `${api.eziTrackerStatus}`, null);
setEziTrackerStatus(resp);
var x= eziStatusCollection; //HELP HERE - Undefined error
debugger;
}
catch (error) {
console.log(error);
}
}
When you wrap it with immediately invoked function it act as kind of similar to a namespace. If you want to keep it same as above code in your question, you can pass down the parameters you want like below,
(async (setVal, val) =>{
try{
const resp = await apiRequest(EcpApiMethod.GET, `${api.eziTrackerStatus}`, null);
setVal(resp);
var x= val; //HELP HERE - Undefined error
debugger;
}
catch (error) {
console.log(error);
}
})(setEziTrackerStatus, eziStatusCollection);
You can read more from here - https://stackoverflow.com/a/2421949/11306028
I have found the answer, the eziClient is nested object so need to access object data against it
return (
<div>
<h2>EziTracker Dashboard Report</h2>
{eziStatusCollection && eziStatusCollection.length >0 && (
<table className="table">
<thead>
<tr>
<th>ClientId</th>
<th>Is Active</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{
eziStatusCollection.map((item, index) => {
return(
<tr key={index}>
<td>{item.eziClient.clientId}</td>
<td>{item.eziClient.isActive}</td>
<td>{item.eziClient.name}</td>
</tr>
)})
}
</tbody>
</table>)}
</div>
);
};
Related
I'm fetching data from an endpoint, and if I use a console.log(data) it shows it correctly.
Image of my array
I only want data.data, so I use console.log(data.data) and apparently It show correctly what I need.
Data that I need
My problem is that I'm trying to show all clients in a table, but it only shows one of them.
This is my code:
import { useEffect, useState } from "react";
function Activity() {
function LoadActivity() {
fetch("https://localhost:7079/client/listClient")
.then((response) => {
return response.json()
})
.then((data) => {
setActivity([data.data])
});
}
const [actividad, setActivity] = useState([]);
useEffect(() => {
LoadActivity();
}, []);
return (
<div>
<h1>Cliente</h1>
<table>
<thead>
<tr>
<th>Id</th>
<th>name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{
actividad.map((client, i )=>(
<tr key={client[i].id}>
<td>{client[i].name}</td>
<td>{client[i].Email}</td>
<td>{client[i].id}</td>
</tr>
))
}
</tbody>
</table>
</div>
);
}
export default Activity;
And this is how it displays:
What is displayed
I tried to do it like this question 3 years ago.
I'm very new with React, and I don't know what I'm missing.
This is how I resolved it
const [equipo, setEquipo] = useState([]);
useEffect(() => {
obtenerDatos();
}, []);
const obtenerDatos = async () =>{
const datos = await fetch('https://localhost:7079/cliente/listarClientes')
const clientes = await datos.json()
setEquipo(clientes.data)
}
I have objects, in the database. I want to grab the userId using axios, but when I tried to console.log() it. It shows undefined. hen I hardcoded it and targeted it by array, it shows.
How can I console log all of userId? I would like to grab it so I can use it as an endpoint for my database
const res = await userRequest.get('user/find/'+userId)
I want to grab the userId only.
import React, { useEffect, useState } from 'react'
import { format } from 'timeago.js'
import { userRequest } from '../../requestMethod'
import './Widgetlg.css'
const WidgetLg = () => {
const Button = ({ type }) => {
return <button className={'widgetLgButton ' + type}>{type}</button>
}
const [orders, setOrders] = useState([])
const [users, setUsers] = useState([])
useEffect(() => {
const getOrders = async () => {
//this is just a shorcut api
try {
const res = await userRequest.get('orders')
setOrders(res.data)
console.log(res.data?.userId)
console.log(res.data)
console.log(res.data[0].userId)
} catch (error) {
console.log(error)
}
}
getOrders()
}, [])
useEffect(() => {
const getUsername = async () => {
try {
const res = await userRequest.get('user/find/')
setUsers(res.data)
} catch (error) {}
}
getUsername()
}, [])
return (
<div className="widgetLg">
<h3 className="widgetLgTitle">Latest Transactions</h3>
<table className="widgetTable">
<tr className="widgetLgTr">
<th className="widgetLgTh">Customer</th>
<th className="widgetLgTh">Date</th>
<th className="widgetLgTh">Amount</th>
<th className="widgetLgTh">Status</th>
</tr>
{orders.map((order) => (
<tr className="widgetLgTr">
<td className="widgetLgUser">
<span className="WidgetLgName"> **I want here to show the username** </span>
</td>
<td className="widgetLgDate"> {format(order.createdAt)} </td>
<td className="widgetLgAmmount">P {order.amount} </td>
<td className="widgetLgStatus">
<Button type={order.status} />
</td>
</tr>
))}
</table>
</div>
)
}
export default WidgetLg
You could try something like this if I understand you correctly
const userIdsArray = res.data.map(d => d.userId);
console.log(userIdsArray);
res.data is an array. To log all elements, you could just iterate over them:
res.data.forEach(el => console.log(el.userId));
The reason that console.log(res.data) gives undefined is that the array itself doesn't have a userId field, only the elements of the array do.
sample image of page so far
Please see the above image. I'm wanting to be able to remove the string in the "skill" column when it is deleted after clicking the "Delete" button on the right. I can delete an Employee using filter() with the Delete button on the left. This removes the entire row from the DOM, which is great, but I would like the Delete button on the right to simply remove the content from the Skill(s) column for that particular employee.
I have tried doing something similar in the deleteSkill() function, but I am not sure how to remove the content of the Skill(s) column without deleting the entire row. The issue lies in my setList() function within my deleteSkill() function. Any ideas would be greatly appreciated.
Here is the code:
import React, { Fragment, useEffect, useState } from 'react';
const List = () => {
const [list, setList] = useState([]);
//DELETE Employee by ID
const deleteEmployee = async (id) => {
try {
const deleteEmployee = await fetch(`http://localhost:5000/employees/${id}`, {
method: "DELETE"
});
setList(list.filter(item => item.employee_uuid !== id));
} catch (err) {
console.error(err.message)
}
};
//DELETE Skill by ID
const deleteSkill = async (id) => {
try {
const deleteSkill = await fetch(`http://localhost:5000/employees/${id}/skills`, {
method: "DELETE"
});
setList(list.filter(item => item.summary !== id));
} catch (err) {
console.error(err.message)
}
};
const getList = async () => {
try {
const response = await fetch("http://localhost:5000/employees")
const jsonData = await response.json();
setList(jsonData);
} catch (err) {
console.error(err.message);
}
};
useEffect(() => {
getList();
}, []);
console.log(list);
return (
<Fragment>
{" "}
<h1 class="text-center">Employee Skills Tracker</h1>
<table class="table mt-5 text-center">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th></th>
<th></th>
<th>Skill(s)</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{list.map(item => (
<tr key={item.employee_uuid}>
<td>{item.firstname}</td>
<td>{item.lastname}</td>
<td>Edit</td>
<td><button className="btn btn-danger" onClick={() => deleteEmployee(item.employee_uuid)}>Delete</button></td>
<td>{item.summary}</td>
<td>Edit</td>
<td><button className="btn btn-danger" onClick={() => deleteSkill(item.employee_uuid)} >Delete</button></td>
</tr>
))}
</tbody>
</table>
</Fragment>
);
};
export default List;
Instead of using list.filter(), use list.map(). The key is that you want to return a 1:1 list of modified elements, not a list without certain elements.
If you want to remove the summary for just a specific employee, I'd recommend
setList(list.map(item => {
if (item.id !== id) {
return item; // not the right employee, pass it through
}
let newItem = {...item};
delete newItem.summary;
return newItem;
}));
It's more complex, because you have to explicitly return what you want, but it's also what you're asking for.
I am learning REST API. I am using the react app for front end and backend for Node js and express server. For API I am using REST API. I am using MongoDB for the database. I successfully display all the data to the browser. I can able to search the data. Now I want to delete the data. I don't know how to delete data from REST API endpoint. I will be really glad if someone help me out. I tested my backend by using Postman. Everything works fine as expected.
This is my backend delete end point
app.delete("/students/:id", async (req, res, next) => {
const id = req.params.id;
try {
student
.remove({ _id: id })
.exec()
.then(data => {
res.json(data);
});
} catch (error) {
console.log(error);
}
});
I export my API END points to React js
export async function deleteStudent(id) {
const response = await fetch(`/students/${id}`, {
method: "DELETE"
});
return response.json();
}
This is the main component where I want to delete the data
import React, { useState, useEffect } from "react";
import { logEntry } from "../Api/Api";
import { deleteStudent } from "../Api/Api";
function Datatable() {
const [total, settotal] = useState([]);
const [searchItem, setsearchItem] = useState({
item: ""
});
const [data, setdata] = useState([]);
const handleChange = e => {
setsearchItem({ item: e.target.value });
};
const getEntries = async () => {
const logEntries = await logEntry();
console.log(logEntries);
settotal(logEntries.count);
setdata(logEntries.students);
};
const nameFilter = data.filter(list => {
return list.name.toLowerCase().includes(searchItem.item.toLowerCase());
});
const deleteData = async id => {
await deleteStudent(id);
};
useEffect(() => {
getEntries();
}, []);
return (
<div>
<div style={{ paddingLeft: "800px" }}>
<input
placeholder="Search student"
onChange={handleChange}
style={{ width: "200px", height: "30px" }}
/>
</div>
<p>Total student: {total} </p>
<table>
<thead>
<tr>
<th>Name</th>
<th>City</th>
<th>Address</th>
<th>Phone</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{nameFilter === "" ? (
<p>Student not found</p>
) : (
nameFilter.map(list => {
return (
<tr>
<td>{list.name}</td>
<td>{list.city}</td>
<td>{list.address}</td>
<td>{list.phone}</td>
<td>{list.email}</td>
<td>
<a
className="waves-effect red btn-small"
onClick={() => deleteData(list.id)}
>
Delete
</a>
</td>
</tr>
);
})
)}
</tbody>
</table>
</div>
);
}
export default Datatable;
I don't know, Am I doing?
This looks like a great start! I'm operating on the understanding that you need to somehow pass the id of the student you want to delete into the URL in deleteStudent() from the 'DELETE' button in your <DataTable> component.
So, first, let's refactor your deleteStudent() function:
export async function deleteStudent(id) {
const response = await fetch(`/students/${id}`, {
method: "DELETE",
});
return response.json();
}
You don't need to send any data with a DELETE request, you just need to hit the correct URL based on the id, which we can pass in to the method and dynamically include in the fetch() call.
Now, you need to find some way to pass that id into the deleteStudent() function. From what I can see, you are pulling in the student data here (I've paraphrased this):
const getEntries = async () => {
// students are pulled in, I'm assuming they have an 'id' property that corresponds to the 'id' that MongoDB has them stored under
const logEntries = await logEntry();
// and now data references the students
setdata(logEntries.students);
};
It looks like then you filter the students here:
const nameFilter = data.filter(list => {
return list.name.toLowerCase().includes(searchItem.item.toLowerCase());
});
And then render the filtered students with a call to .map(). This is where you can pass the id along in the onClick handler, assuming that you DO have an id field on these list elements. If you don't, then you will need to find a way to add the id in to this data:
nameFilter.map(list => {
return (
<tr>
<td>{list.name}</td>
<td>{list.city}</td>
<td>{list.address}</td>
<td>{list.phone}</td>
<td>{list.email}</td>
<td>
<a
className="waves-effect red btn-small"
onClick={() => deleteData(list.id)} // this is where the id should get passed on to the handler, and then dynamically included in the DELETE /students/:id url
>
Delete
</a>
</td>
</tr>
);
})
Then, in your deleteData() function, you will receive the id as a param, and you can call your deleteStudent(id) function to make the request to the backend:
const deleteData = async id => {
await deleteStudent(id);
};
There are some other things that need work, but you have the general idea correct! I'll give some hints towards further improvements below.
Do these need to be separate, or can they be combined?
import { logEntry } from "../Api/Api";
import { deleteStudent } from "../Api/Api";
Maybe clean up the DELETE route-handler:
app.delete("/students/:id", async (req, res, next) => {
const id = req.params.id;
try {
// generally, Mongoose Model's are represented with TitleCase
Student
.remove({ _id: id })
.exec() // is this needed? https://mongoosejs.com/docs/api/model.html#model_Model-remove
.then(data => {
res.json(data);
});
} catch (error) {
console.log(error);
}
});
There seems to be some extra state/hooks lying around in this Datatable:
function Datatable() {
// ... bunch of code
// do you need state for this?
const [removeStudent, setremoveStudent] = useState([]);
// ... more code
const getEntries = async () => {
// ...
setremoveStudent(deleteData); // not sure this is needed...
};
I am having issues calling a function inside the map function in this React component.
This component should display a hierarchy of sorts in a table format. It should display a galaxys name and year discovered. Then it should iterate through and display all the known star systems in that galaxy, and finally, display each known planet in each of those star systems.
I've tried numerous suggestions that I've seen on SO and other websites.
When I do not use 'this' in front of the function, I get this error "populatePlanetData is not defined"
When I do use 'this', I get this error "this.populatePlanetData is not a function"
One of the answers I found suggested using an arrow function as suggested in this answer: "this" is undefined inside map function Reactjs
This one also suggests using arrow functions:
Calling functions inside a map() function in React render()
But even with that arrow function, I still get the above errors. I can't figure out what I'm doing wrong. Is there anything obvious that's wrong or not done the correct way?
Here is the component:
import React, { Component } from 'react';
export class GetTestGalaxy extends Component {
static displayName = GetTestGalaxy.name;
constructor(props) {
super(props);
this.state = { galaxy: null, systems: [], planets: [], loading: true };
}
componentDidMount() {
this.populateGalaxyData(482);
this.populateSystemData(482);
}
static renderGalaxyTable(galaxy, systems, planets) {
return (
<table>
<thead>
<tr>
<th>Galaxy Name</th>
<th>Year</th>
</tr>
</thead>
<tbody>
<tr key={galaxy.id}>
<td>{galaxy.name}</td>
<td>{galaxy.year}</td>
</tr>
{this.systems.map(system =>
<tr>
<td>{system.name}</td>
<td>
{this.populatePlanetData(system.id).map(planet =>
<span>{planet.name}</span>
)}
</td>
</tr>
)}
</tbody>
</table>
);
}
render() {
let contents = this.state.loading
? <p><em>Loading...</em></p>
: GetTestGalaxy.renderGalaxyTable(this.state.galaxy, this.state.systems, this.state.planets);
return (
<div>
<h1 id="tabelLabel" >Galaxy Information</h1>
{contents}
</div>
);
}
async populateGalaxyData(id) {
const response = await fetch('https://localhost:44389/api/galaxylist/' + id);
const data = await response.json();
this.setState({ galaxy: data, loading: false });
}
async populateSystemData(id) {
const response = await fetch('https://localhost:44389/api/systemlist/GetSystems/' + id);
const data = await response.json();
const result = Object.values(data);
this.setState({ systems: result, loading: false });
}
async populatePlanetData(id) {
const response = await fetch('https://localhost:44389/api/planetlist/GetPlanets/' + id);
const data = await response.json();
const result = Object.values(data);
this.setState({ planets: result, loading: false });
}
}