Add stop condition to map in React [duplicate] - javascript

This question already has answers here:
How to break .map function
(4 answers)
Closed 1 year ago.
Having the following code snippet:
<TableHead>
{documents.map((docs, i) => (
<TableRow key={i}>
<TableCell>
{{docs.name}
</TableCell>
</TableRow>
))}
</TableHead>
How can I make it run only for a finite number of iterations? In my particular case I want it to run for 10 times.
Tried to add a condition like i < 10 && ... but it doesn't work.
<TableHead>
{documents.map((docs, i) => (
{ i < 10 &&
<TableRow key={i}>
<TableCell>
{{docs.name}
</TableCell>
</TableRow>
}
))}
</TableHead>
Any ideas?

Slice the first 10 elements of the array:
documents.slice(0, 10).map(/*...*/)

You need to filter documents before maping
<TableHead>
{documents
.filter((doc, i) => i < 10)
.map((doc, i) => (
<TableRow key={i} >
<TableCell>
{doc.name}
</TableCell>
</TableRow>
))
}
</TableHead>

Related

How to create a table cell from each element of array in react js using MUI Table

I want to create a cell for each value of my array which is stored in a array of objects but what is going on is all the data which is in the array which is inside the object is not getting rendered as individual table cell. How to achieve
import {Paper,Table,TableBody,TableCell,TableContainer,TableHead,TableRow} from "#mui/material";
export function Schedule(prop){
let data = prop.data
console.log(data)
return(
<>
{!data ? "" :
<TableContainer>
{data.map((result) =>(
<Table>
<TableHead>
<TableRow>
<TableCell>Fact Name</TableCell>
<TableCell>{result.slotFree}</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell>
{result.name}
</TableCell>
<TableCell>
{result.status}
</TableCell>
</TableRow>
</TableBody>
</Table>
))}
</TableContainer>
}
</>
)
}[![This is my incoming data array of object](https://i.stack.imgur.com/sygfU.png)](https://i.stack.imgur.com/sygfU.png)
that result
I want that each free slot comes as an individual cell and should not render out in the same line This is the output](https://i.stack.imgur.com/jMTFC.png)
I want the time and slot status to be in the same column

Access cart data object to create total amount

im creating an array for list cart items, works well, but wanted to know how can i access to each item properties to create the total order amount outside table item
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell className={classes.hideOnMobile}>
</TableCell>
<TableCell>PRODUCTO</TableCell>
<TableCell>PRECIO</TableCell>
<TableCell align="center">CANTIDAD</TableCell>
<TableCell align="right">TOTAL</TableCell>
<TableCell align="right"></TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map((row) => (
<Item data={row} {...props} />
))}
</TableBody>
<TableFooter className={classes.table}>
<TableCell>
</TableCell>
<TableCell align="right">TOTAL ORDER</TableCell>
<TableCell align="left">"TOTAL GOES HERE"</TableCell>
</TableFooter>
</Table>
This is my JSON data
0:
id: 31
image: "https://example.com/test.jpg"
name: "Product name 1"
price: 3
quantity: 13
total: 39
__proto__: Object
1: {id: 2, name: "Product name 2", price: 3, …}
length: 2
I would have a total variable somewhere in the component (a class property in this example, could very well just be a variable if you are using functional components), and accumulate the total as you loop over your data. That way, you only have to loop over your data set once. Something like this:
class App extends React.Component {
data = {/* your data */}
total = 0;
render() {
return (
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell className={classes.hideOnMobile}>
</TableCell>
<TableCell>PRODUCTO</TableCell>
<TableCell>PRECIO</TableCell>
<TableCell align="center">CANTIDAD</TableCell>
<TableCell align="right">TOTAL</TableCell>
<TableCell align="right"></TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.data.map((row) => (
this.total += row.total;
return <Item data={row} {...props} />
))}
</TableBody>
<TableFooter className={classes.table}>
<TableCell>
</TableCell>
<TableCell align="right">TOTAL ORDER</TableCell>
<TableCell align="left">{this.total}</TableCell>
</TableFooter>
</Table>
);
}

React - Material UI table to contain a dropdown in each row

so I have this Table I've rendered its rows from an array map as shown below
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>Object Name</TableCell>
<TableCell align="center">Object Field and Values</TableCell>
</TableRow>
</TableHead>
<TableBody>
{union &&
unionArray.map((row) => (
<TableRow key={row.name}>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
{Object.keys(row).map((key) =>
key === "name" ? (
""
) : (
<TableCell align="center">
{/*insert dropdown select*/}
<FormControl
variant="outlined"
className={classes.formControl}
>
<InputLabel htmlFor="outlined-age-native-simple">
Values
</InputLabel>
<Select
native
label="Value"
>
<option aria-label="None" value="" />
<option>{key}:{row[key]}</option>
</Select>
</FormControl>
</TableCell>
)
)}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
the array of objects where I mapped from is shown below. i.e UnionArray
my problem is the rows that have a third key/value pair are rendering as entire table cell, I just want them to be part of the dropdown. the output now is something like this
you could modify your array you get from the api and do sth like this:
let modifiedUnion = unionArray.map(el=>{
let tempObj={}
let values=[]
Object.keys(el).map(key=>
if(key!=="name"){
tempObj.values = values.push({[key]:el[key]})
}else{
tempObj.name = el.name
}
return tempObj
})
and after that write this part like this:
{modifiedUnion.map((row) => (
<TableRow key={row.name}>
<TableCell align="center">
{row.name}
</TableCell>
<TableCell align="center">
<FormControl variant="outlined" className={classes.formControl}>
<InputLabel htmlFor="outlined-age-native-simple">
Values
</InputLabel>
<Select native label="Value">
<option aria-label="None" value="" />
{row.values.map((key) =>
<option>{Object.keys(key)[0]}:{Object.values(key)[0]}</option>
)}
</Select>
</FormControl>
</TableCell>
</TableRow>
))}
I don't have enough reputations to comment but the answer lies in #lakshya's response and #ahmed's comment. Object.keys will return null for when key === 'name' but it will return valid JSX for when the keys aren't name, hence, your table cell having 2 dropdowns.
As for how to go about formatting the response, you can format your loop like in the image attached.
Convert the object to a format like
[{
name: 'obj1',
values: [
{
a: 1
}
]
},
{
name: 'obj3',
values: [
{
c: 2,
d: 5
}
]
}
]

Scrolling not working in Firefox, I have a table which loadsMore when user scrolls down but it stops for firefox

Scrolling not working in Firefox, I have a table which loadsMore when user scrolls down but it stops for firefox. If i zoom out then the scrolling works properly. Any ideas what I can do?.
Works perfectly in all other browsers except Firefox
function TableWaypoint({ onLoadMore = () => null, offset, pending, columnsCount }) {
return (
<>
<TableRow>
<TableCell colSpan={columnsCount} className={styles.lastCell}>
{offset !== 0 && <Waypoint onEnter={onLoadMore} />}
</TableCell>
</TableRow>
{pending &&
Array.from(new Array(3)).map((row, index) => (
<TableRow key={index}>
{Array.from(new Array(columnsCount)).map((Cell, index) => (
<TableCell key={index}>
<Skeleton variant="rect" />
</TableCell>
))}
</TableRow>
))}
</>
)
}
<TableWaypoint
columnsCount={columns.length}
onLoadMore={onLoadMore}
offset={data.length}
pending={pending}
/>

Javascript Can't read second element of array that is array

I am trying to access all elements of my array except the first one but i get empty values.
renderTableBody = thisService => {
console.log(thisService); // in the image it's the printed array
console.log(thisService.length); // in the image is the number 1
return thisService.slice(1).map(item =>
item.map(k => (
<TableRow key={k.kpiId}>
<TableCell align="left" component="th" scope="row">
{k.kpiId}
</TableCell>
<TableCell align="left">{k.kpiName}</TableCell>
<TableCell align="left">{k.targetDisplay}</TableCell>
<TableCell align="left">{k.targetDisplay}</TableCell>
<TableCell align="left">{k.reason}</TableCell>
<TableCell align="left">{k.action}</TableCell>
<TableCell align="left">{k.dueDate}</TableCell>
<TableCell align="left">{k.owner}</TableCell>
</TableRow>
))
);
};
When i log the length of array it prints 1 when it actually has 2 elements. When i try to access only the second element of the array, i get "undefined".
This is the logged to console object:
Am i doing something wrong in accessing the second element of my array which is an array itself?
EDIT
The part of code where i am calling the function renderTableBody:
<div id="servicesInputs">
{kpiServInputs.map((service) => (
<div key={service[0].id} id={service[0].id}>
<div align="left">
<h4>{service[0].serviceName}</h4>
</div>
<div>
<Paper >
<Table>
<TableHead>
<TableRow>
<TableCell align="left">#</TableCell>
<TableCell align="left">KPI</TableCell>
<TableCell align="left">Target</TableCell>
<TableCell align="left">Actual</TableCell>
<TableCell align="left">Reason</TableCell>
<TableCell align="left">Action</TableCell>
<TableCell align="left">Due Date</TableCell>
<TableCell align="left">Owner</TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.renderTableBody(service)}
</TableBody>
</Table>
</Paper>
<br/>
</div>
</div>
))}
</div>
renderTableBody = thisService => {
console.log(thisService); // in the image it's the printed array
console.log(thisService.length); // in the image is the number 1
return thisService[1].map(item =>
item.map(k => (
<TableRow key={k.kpiId}>
<TableCell align="left" component="th" scope="row">
{k.kpiId}
</TableCell>
<TableCell align="left">{k.kpiName}</TableCell>
<TableCell align="left">{k.targetDisplay}</TableCell>
<TableCell align="left">{k.targetDisplay}</TableCell>
<TableCell align="left">{k.reason}</TableCell>
<TableCell align="left">{k.action}</TableCell>
<TableCell align="left">{k.dueDate}</TableCell>
<TableCell align="left">{k.owner}</TableCell>
</TableRow>
))
);
};
This should be your code because as #Dupocas pointed out, thisService is an array that looks like [{Object}, [Array]].
When you run slice on this and a map on the result, what you are doing is trying to map through the outer array of something like [['stuff you need']]. This outer array has a length of 1 and would act exactly as you are seeing it act. By changing the slice to directly access the first index of thisService, you will be looping though the info you need.
The problem was that the array was populated asynchronously with making a fetch call to an api. What worked for me was making the return async and waiting the fetch call to finish and then populating the array.
The code:
function fetchKpiServicesInputs(state) {
let serviceInputs = [];
return async dispatch => {
for (var i = 0; i < servicesCount; i++) {
let newServ = [];
newServ.push({id: i, serviceName: kpiServices[i].name });
let url = "apiUrl";
const response = await fetch(url, {
method: 'GET'
});
const responseData = await response.json();
if (Object.keys(responseData).length > 0) {
newServ.push(responseData);
}
serviceInputs.push(newServ);
}
dispatch(receiveKpiServiceInputs(serviceInputs));
};
Thanks for the help everyone!

Categories