How to get rowIndex in Reactjs? - reactjs

I have a table using normal HTML in reactjs:
const [user, setUser] = useState(null);
useEffect(() => {
axios
.get("http://localhost:8080/api/users")
.then((response) => {
setUser(response.data);
});
}, [url]);
const [rowIndex, setRowIndex] = useState("");
if (user) {
return (
<div>
<table className="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
<th scope="col">Department</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{user.map((item) => (
<tr>
<td>{item.name}</td>
<td>{item.age}</td>
<td>{item.department}</td>
<td><button>Click</button></td>
</tr>
))}
</tbody>
</table>
</div>
);
}
If in Javascript, I can simply set <tr onclick="getIndex(this)"> and calling function getIndex(x) {console.log(x.rowIndex)} to get the row number.
But it's not working in ReactJS. How can I get the rowIndex in ReactJS?

Use index inside your map method and then use this variable inside your button's onClick method
const [user, setUser] = useState(null);
useEffect(() => {
axios
.get("http://localhost:8080/api/users")
.then((response) => {
setUser(response.data);
});
}, [url]);
const [rowIndex, setRowIndex] = useState("");
if (user) {
return (
<div>
<table className="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Age</th>
<th scope="col">Department</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{user.map((item, index) => (
<tr>
<td>{item.name}</td>
<td>{item.age}</td>
<td>{item.department}</td>
<td><button onclick={() => setRowIndex(index)}>Click</button></td>
</tr>
))}
</tbody>
</table>
</div>
);
}

Related

How can i create dropdown that only show selected number of an API list with React

I trying to create a Dropdown that shows some list of an API depending on the number you selected on the dropdown.
For example, if in the dropdown if selected option 30 then it will show the list of 30 from 1-30. If I changed the option to 50 it will show 1-50. How can I do that?
The code :
const [data, setData] = useState([]);
const [id, setId]= useState('');
const [index, setIndex] = useState(10)
useEffect(() => {
const loadData = async () => {
await fetch(`https://swapi.dev/api/people/${id}/`)
.then((response) => response.json())
.then((ReceivedData) => setData(ReceivedData));
}
loadData()
},[id]);
return(
<select>
<option selected >10</option>
<option selected >50</option>
<option selected >60</option>
</select>
{data.map((datas,index){
<table className="table">
<tbody>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Height</th>
<th scope="col">Mass</th>
<th scope="col">Hair Color</th>
<th scope="col">Eye Color</th>
</tr>
</thead>
<tr key={index}>
<th scope="row">{datas.name}</th>
<td>{datas.height}</td>
<td>{datas.mass}</td>
<td>{datas.hair_color}</td>
<td>{datas.eye_color}</td>
</tr>
</tbody>
</table>)}
)
The API you have given has pagination implemented. So you can query it a few times to get the required amount of results. For 50 call 5 times while incrementing page param. Each request gives 10 people per request.
function App() {
const [data, setData] = React.useState([]);
const [id, setId] = React.useState("10");
const [index, setIndex] = React.useState(10);
React.useEffect(() => {
const loadData = async () => {
const requests = Array.from({ length: parseInt(id) / 10 }, (_, i) =>
fetch(`https://swapi.dev/api/people/?page=${i + 1}`)
);
const responses = await Promise.all(requests);
const promises = responses.map((response) => response.json());
const output = await Promise.all(promises);
setData(output.map((o) => o.results)?.flatMap((arr) => arr));
};
loadData();
}, [id]);
return (
<div>
<select onChange={(e) => setId(e.target.value)}>
<option selected>10</option>
<option selected>50</option>
<option selected>60</option>
</select>
{data.map((datas, index) => (
<table className="table">
<tbody>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Height</th>
<th scope="col">Mass</th>
<th scope="col">Hair Color</th>
<th scope="col">Eye Color</th>
</tr>
</thead>
<tr key={index}>
<th scope="row">{datas.name}</th>
<td>{datas.height}</td>
<td>{datas.mass}</td>
<td>{datas.hair_color}</td>
<td>{datas.eye_color}</td>
</tr>
</tbody>
</table>
))}
</div>
);
}

when there is no data in my json file that time my component didn't display

This is my Table.js file code.
In this component i pass UserData which hold data that come from the server, handleEditButton method for update my data and handleDeleteButton for delete my data. When UserData is empty than i'm return "No data found" other wise it's show's data in tabular format
const Table = ({ UserData, handleEditButton, handleDeleteButton }) => {
if (UserData == '') {
return (
<>
{
<h2>N Data Found</h2>
}
</>
)
}
else {
return (
<>
{
<table cellSpacing={0} cellPadding={0} className={tableStyles.details}>
<thead>
<tr>
<th className={tableStyles.table}>Id</th>
<th className={tableStyles.table}>Name</th>
<th className={tableStyles.table}>Address</th>
<th className={tableStyles.table}>E-mail</th>
<th className={tableStyles.table}>Mobile No</th>
<th className={tableStyles.table}>Gender</th>
<th className={tableStyles.table}>City</th>
<th className={tableStyles.table}>Action</th>
</tr>
</thead>
<tbody>
{
(UserData && UserData.map((user) => (
<tr>
<th key={user.id}>{user.id}</th>
<td className={tableStyles.name}>{user.name}</td>
<td className={tableStyles.address}>{user.address}</td>
<td className={tableStyles.mail}>{user.mail}</td>
<td>{user.no}</td>
<td>{user.gender}</td>
<td>{user.city}</td>
<td colSpan={2} className={tableStyles.btnGroup}>
<button className={tableStyles.editBtn} onClick={(e) => { handleEditButton(user.id) }}>Edit</button>
<button className={tableStyles.deleteBtn} onClick={(e) => { handleDeleteButton(user.id) }}>Delete</button>
</td>
</tr>
)))
}
</tbody>
</table>
}
</>
)
}
}
You missed adding a ternary condition.
You can check with the following code.
const Table = ({ UserData, handleEditButton, handleDeleteButton }) => {
{
UserData == "" ? (
<h2>No Data Found</h2>
) : (
<table cellSpacing={0} cellPadding={0} className={tableStyles.details}>
<thead>
<tr>
<th className={tableStyles.table}>Id</th>
<th className={tableStyles.table}>Name</th>
<th className={tableStyles.table}>Address</th>
<th className={tableStyles.table}>E-mail</th>
<th className={tableStyles.table}>Mobile No</th>
<th className={tableStyles.table}>Gender</th>
<th className={tableStyles.table}>City</th>
<th className={tableStyles.table}>Action</th>
</tr>
</thead>
<tbody>
{UserData &&
UserData.map((user) => (
<tr>
<th key={user.id}>{user.id}</th>
<td className={tableStyles.name}>{user.name}</td>
<td className={tableStyles.address}>{user.address}</td>
<td className={tableStyles.mail}>{user.mail}</td>
<td>{user.no}</td>
<td>{user.gender}</td>
<td>{user.city}</td>
<td colSpan={2} className={tableStyles.btnGroup}>
<button
className={tableStyles.editBtn}
onClick={(e) => {
handleEditButton(user.id);
}}
>
Edit
</button>
<button
className={tableStyles.deleteBtn}
onClick={(e) => {
handleDeleteButton(user.id);
}}
>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
);
}
};

Issue with mapping through the data - React

Do you know why am I not a able to map through the todos? I am following tutorial online and I have it exactly the same as the other guy but It's not mapping through the data. I get the json back and I can see the todos inside of the client-side console.
import React, { Fragment, useEffect, useState } from "react";
const ListTodos = () => {
const [todos, setTodos] = useState([]);
const getTodos = async () => {
try {
const response = await fetch("http://localhost:5000/todos");
const jsonData = await response.json();
setTodos(jsonData);
} catch (err) {
console.error(err.message);
}
};
useEffect(() => {
getTodos();
}, []);
return (
<Fragment>
<table className="table mt-5 text-center">
<thead>
<tr>
<th>Description</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{todos.map((todo) => {
<tr>
<td>{todo.description}</td>
<td>Edit</td>
<td>Delete</td>
</tr>;
})}
</tbody>
</table>
</Fragment>
);
};
Thanks
You should return the JSX if you are using curly braces in function. Like This
{todos.map((todo) => {
return (<tr>
<td>{todo.description}</td>
<td>Edit</td>
<td>Delete</td>
</tr>;
)})}
Else use parentheses to directly return , Like This
{todos.map((todo) => (<tr>
<td>{todo.description}</td>
<td>Edit</td>
<td>Delete</td>
</tr>
))}
you should use round brackets insted of curly braces in the map function
return (
<Fragment>
<table className="table mt-5 text-center">
<thead>
<tr>
<th>Description</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{todos.map((todo) => (
<tr>
<td>{todo.description}</td>
<td>Edit</td>
<td>Delete</td>
</tr>
))}
</tbody>
</table>
</Fragment>
);

React-Hooks: How to create reusable data table component?

In my application, I need to reuseable data table component. Where I can change table-header & table-body with dynamic content.
<table className="table table-hover">
<thead>
<tr>
<th>#</th>
<th>Image</th>
<th>Title</th>
<th>Publish Date</th>
</tr>
</thead>
<tbody>
{data &&
data.map(item => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.image}</td>
<td>{item.title}</td>
<td>{item.publishDate}</td>
</tr>
))}
</tbody>
</table>
See if this works! https://stackblitz.com/edit/react-ie2rt6
import React from "react";
const Table = ({ headers, data }) => {
return (
<div>
<table>
<thead>
<tr>
{headers.map(head => (
<th>{head}</th>
))}
</tr>
</thead>
<tbody>
{data.map(row => (
<tr>
{headers.map(head => (
<td>{row[head]}</td>
))}
</tr>
))}
</tbody>
</table>
</div>
);
};
export default Table;
This might help
const CustomTable = ({header, posts}) => {
return (
<table>
<thead>
<tr>
<th>#</th>
<th>{header.image}</th>
<th>{header.title}</th>
<th>{header.publishedDate}</th>
</tr>
</thead>
<tbody>
{posts &&
posts.map(item => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.image}</td>
<td>{item.title}</td>
<td>{item.publishDate}</td>
</tr>
))}
</tbody>
</table>
);
}
You can pass header and posts array wherever you need it.
<div className='table'>
<CustomTable header={header} posts={posts} />
</div>

Display no results when table empty in React

I have a table of rows that display contact information. I'd like to have it render a messasge of "No contacts" when the listItems array is 0. I tried creating a const noEntries variable and setting it with the array to 0, and using {noEntries No entries}, but this is throwing an error.
class ContactList extends Component {
constructor(props) {
super(props);
this.createContact = this.createContact.bind(this);
}
delete(key) {
this.props.delete(key);
}
createContact(item) {
return <tr key={item.key}>
<td>{item.firstname}</td>
<td>{item.lastname}</td>
<td>{item.phone}</td>
<td><i className="fas fa-trash-alt" onClick={() => { if (window.confirm('Are you sure you want to delete ' + item.firstname + ' ' + item.lastname + ' from your contacts?')) this.delete(item.key)}}></i></td>
</tr>
}
render() {
const contactEntries = this.props.entries;
const listItems = contactEntries.map(this.createContact);
return (
<table className="mui-table mui-table--bordered">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
{listItems}
</tbody>
</table>
);
}
};
export default ContactList;
in your render() do like this:
render() {
const contactEntries = this.props.entries;
const listItems = contactEntries.map(this.createContact);
return (
contactEntries.length > 0?
<table className="mui-table mui-table--bordered">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
{listItems}
</tbody>
</table>:<span>No results</span>
);
}
check the number of records in contactEntries using ternary operator if length ==0 then return no data component else return rows
const listItems = contactEntries && contactEntries.length >0
? contactEntries.map(this.createContact)
: <tr key={item.key}>
<td rowspan="3">No data</td
</tr>

Resources