arrange elements in vertical order - reactjs

Found some answers, but all are implemented on multi dimension array.
I have a scenario, where I need to render the array elements in the vertical order.
Expected Behavior:
Get the length of given array and split the array into four columns.
Each column should have max of 6 items in it.
Expected Output:
1 7 13 19
2 8 14 20
3 9 15 21
4 10 16 22
5 11 17 23
6 12 18 24
Sample Array:
{
"items": [
{
"val": "1"
},
{
"val": "2"
},
{
"val": "3"
},
{
"val": "4"
},
{
"val": "5"
},
{
"val": "6"
},
{
"val": "7"
},
{
"val": "8"
},
{
"val": "9"
}
]
}
This is what I tried, not able to achieve the expected output.
createList(list, index) {
const max = Math.max.apply(null, list.items.map((x, i) => (i + 1) / 4));
return Array.from({ length: max }, function(item, index) {
return <div className="row" key={index}>
{list.items.slice(0, max).map((x, i) => (
<div className="col-3" key={i}>
{x.val}
</div>
))}
</div>;
});
}

There's probably tons of way to do this but i came up with this solution using lodash:
renderColumn(row) {
// map through columns
const columns = row.map(column => (
<td key={column}>{column}</td>
));
return columns;
}
render() {
// Create an array of length 50
let items = [];
for (let i=0; i<50; i++) {
items.push({val:i});
}
/** Transform the array in something like this:
* items: [
* [1, 7, 13, 19],
* [2, 8, 14, 20],
* [3, 9, 15, 21],
* [4, 10, 16, 22],
* [5, 11, 17, 23],
* [6, 12, 18, 24],
* ]
*/
// Get only 24 first items as it is a 4x6 matrix
items = items.slice(0, 24);
const res = _.reduce(items, (result, value, key) => {
const index = key % 6;
(result[index] || (result[index] = [])).push(value.val);
return result;
}, {});
// map through the rows of the arrays
const rows = _.map(res, row => {
const column = this.renderColumn(row);
return <tr>{column}</tr>;
});
return (
<table>
<tbody>
{rows}
</tbody>
</table>
);
}
I hope you get the point :)
Here is a sandbox with the code

Related

Type for sending array of objects to child component so index [1] doesn't have to be specified

The API returns an array of objects that looks like this:
[
{
"id": 1,
"odd": 7,
"even": 42
},
{
"id": 2,
"odd": 1,
"even": 2
},
{
"id": 3,
"odd": 31,
"even": 6
},
{
"id": 4,
"odd": 17,
"even": 62
},
{
"id": 5,
"odd": 13,
"even": 4
},
{
"id": 6,
"odd": 21,
"even": 12
}
]
I want to pass this to a child component that iterates through the area of objects and prints out id, odd, and even.
What I can get working is doing the following:
// ParentComponent.tsx
...
<ChildItems {...response} />
...
// ChildComponent.tsx
type ReponseProps = {
id: number;
odd: number;
even: number;
}[];
const ChildItems = (props: ResponseProps): JSX.Element => {
console.log(props);
return <></>;
};
Which creates an object that looks like:
{
"0": {
"id": 1,
"odd": 7,
"even": 42
},
"1": {
"id": 2,
"odd": 1,
"even": 2
},
"2": {
"id": 3,
"odd": 31,
"even": 6
},
"3": {
"id": 4,
"odd": 17,
"even": 62
},
"4": {
"id": 5,
"odd": 13,
"even": 4
},
"5": {
"id": 6,
"odd": 21,
"even": 12
}
}
Then I have to do something like the following to access each element:
const ChildItems = (props: SolutionProps): JSX.Element => (
<>
{
Object.entries(props).map((item, index) => {
return (
<p key={item[1].id}>{item[1].even} - {item[1].odd}</p>
)
})
}
</>
);
What strikes me as weird is having to do item[1]: messy and seems like it shouldn't be necessary.
So that is my question: How should I build the passing of props to a child component, and type in the child component, to get around having to specify the index?
I've tried doing the following in the parent component:
// ParentComponent.tsx
...
<ChildComponent res={response} />
...
// ChildComponent.tsx
const ChildItems = (res: SolutionProps): JSX.Element =>
...
But always get a: Property 'res' does not exist on type 'IntrinsicAttributes & SolutionProps'.
Probably a way to this and I'm just screwing it up.
Props should be a plain object, not an array, where each property of the props argument is treated similarly to an argument in a normal function. Right now, you're typing the props as an array, and you're also not passing an array, but an object as props when you do
<ChildItems {...response} />
(which spreads each enumerable own property of the response into the props object - resulting in your { 0: ... 1: ... } structure that's hard to work with)
Change to something like:
<ChildItems {...{ response }} />
// or
<ChildItems response={response} />
and
const ChildItems = ({ response }: { response: ResponseProps }) => {

How to create 2D array dynamically with the ES6 approach?

I've been trying to create 2D arrays from an array dynamically with a function; however, I couldn't break out of the ES3 old school approach. Does anybody know how to refactor the following code using the ES6 approach?
const nums = [1,2,3,4,5,6,7,8,9,10,11,12];
const letters = ['a','b','c','d','e','f','g','h','i'];
function create2D(arr,set) {
const result = [];
for (let i = 0; i < arr.length; i+=set) {
const rows = arr.slice(i,i+set);
result.push(rows);
}
return result;
}
console.log(create2D(nums,4)); // [ [ 1, 2, 3, 4 ], [ 5, 6, 7, 8 ], [ 9, 10, 11, 12 ] ]
console.log(create2D(letters,3)); // [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ], [ 'g', 'h', 'i' ] ]
I've only gotten this far with "reduce" and couldn't find out how to replicate the addition assignment "i+=set" from the for loop. This is what I have so far...
function create2D(arr,set) {
return arr.reduce((result,item,i) => {
result.push(arr.slice(i,i+set));
return result;
},[]);
}
console.log(create2D(nums, 4)); // [ [1, 2, 3, 4],[2, 3, 4, 5],[3, 4, 5, 6], ...]
You were pretty close. Just need to modify it slightly:
const nums = [1,2,3,4,5,6,7,8,9,10,11,12];
const letters = ['a','b','c','d','e','f','g','h','i'];
function create2D(arr,set) {
return arr.reduce((result,item,i) => {
let startVal = i*set //We want to jump through the startPoints. Not iterate through them all
if (startVal < arr.length-1) {
result.push(arr.slice(startVal,startVal+set));
}
return result;
}, []);
}
console.log(create2D(nums, 4)); // [ [1, 2, 3, 4],[2, 3, 4, 5],[3, 4, 5, 6], ...]
console.log(create2D(nums, 3));
console.log(create2D(letters, 3));

React object, display key names

I have a demo here
It's a simple React TypeScript app where I am displaying an object
The object is like
{
"default": {
"ProductSize": {
"min": 32
},
"ProductHeight": {
"min": 15
},
"ProductWeight": 50
},
"ProductOne": {
"ProductSize": {
"min": 20,
"max": 15
},
"ProductHeight": {
"min": 50,
"max": 87
},
"ProductSpacing": 90,
"ProductWeight": 100
},
"ProductTwo": {
"ProductSize": {
"min": 43,
"max": 67
},
"ProductHeight": {
"min": 12,
"max": 78
},
"ProductSpacing": 34,
"ProductWeight": 56
}
}
I can pull out parts of the jsons like
<ul>
{Object.keys(ProductData).map(key => (
<li key={key}>{ProductData[key].ProductSize.min}</li>
))}
</ul>
but how can I get the key name for each block
So I want to list
default
ProductOne
ProductTwo
ProductThree
I have tried
<li key={key}>{ProductData[key].key}</li>
but I get an empty list item
Answer
You already have keys array through Object.keys(ProductData)
So it will be simple
<ul>
{Object.keys(ProductData).map(key => (
<li key={key}>{key}</li>
))}
</ul>
Theory
Object.keys(obj) returns array of obj keys, MDN docs
const obj = {
foo: 12
bar: 'bar'
}
// will return ['foo', 'bar']
const keys = Object.keys(obj);
// will return <li key="foo"}>foo</li><li key="bar">bar</li>
const items = keys.map((key) => <li key={key}>{key}</li>)
If you will need a key and a value together see Object.entries() docs
// will return [['foo', 12], ['bar', 'bar']]
const entries = Object.entries(obj);
// will return <li key="foo"}>foo: 12</li><li key="bar">bar: bar</li>
const items = entries.map(([key, value]) => <li key={key}>{key}: {value}</li>);
For [key, value] syntax see destructuring docs

Return an array of values obtained from calling reduce() of JS

I have a json array as follows
var arrayVal = [{id:"1",name:"A", sAge: 20, eAge:30},{id:"2",name:"B", sAge: 30, eAge:50},{id:"2",name:"B", sAge: 20, eAge:40},{id:"3",name:"C", Aage: 20, eAge:50},{id:"4",name:"D", sAge: 10, eAge:30}];
I want to take difference of sAge and eAge of each id and sum the final value if there are multiple diff values of same id. For that I have the following code
const ages = array.reduce((a, {id, sAge, eAge}) => (a[id] = (a[id] || 0) + eAge - sAge, a), {});
console.log(ages);
output of the above code snippet is as follows
{
"1": 20,
"2": 50,
"3": 20,
"4": 10
}
But If I want to obtain an array as follows after using reduce(), how can I achieve that?
[{id:"1",name:"A", hours:"20"},{id:"2",name:"B", hours:"50"},{id:"3",name:"C", hours:"20"},{id:"5",name:"D", hours:"10"}]
The following does the job but I didn't obtain your expected values
var arrayVal = [{id:"1",name:"A", sAge: 20, eAge:30},{id:"2",name:"B", sAge: 30, eAge:50},{id:"2",name:"B", sAge: 20, eAge:40},{id:"3",name:"C", sAge: 20, eAge:50},{id:"5",name:"D", sAge: 10, eAge:30}];
const ages = Object.values(arrayVal.reduce((a, {id, name, sAge, eAge}) => {
let difference = eAge - sAge;
if(a.hasOwnProperty(id)) {
a[id].hours+= difference;
} else {
a[id] = {
id:id,
name:name,
hours:difference
}
}
return a;
}, {}));
Output
[
{
"id": "1",
"name": "A",
"hours": 10
},
{
"id": "2",
"name": "B",
"hours": 40
},
{
"id": "3",
"name": "C",
"hours": 30
},
{
"id": "5",
"name": "D",
"hours": 20
}
]

How do i loop through this in react

When i use map().I got this error "this.props.getCart.items.map is not a function"
{
"70":
[
{
"numberPick": 13,
"numberPrice": 200
},
{
"numberPick": 44,
"numberPrice": 300
}
],
"81":
[
{
"numberPick": 31,
"numberPrice": 50
},
{
"numberPick": 22,
"numberPrice": 90
},
{
"numberPick": 38,
"numberPrice": 50
}
]
}
This is how i get it #redux
var newData = (state.items[action.parent] === undefined)?[]:state.items[action.parent]
state = {
...state,
items:{
...state.items,
[action.parent]:[...newData,{
numberPick:action.item,
numberPrice:action.price
}]
}
}
Results that i want.Should be like this
Your parent id is 70:
first: itemID = 13 and price = 200
second: itemID = 44 and price = 200
Your parent id is 81:
first: itemID = 31 and price = 50
second: itemID = 22 and price = 90
Can anyone please help me.Thank you so much
There is no map for Object, but you want use below
Object.keys(myObject).map(function(key, index) {
myObject[key] *= 2;
});
console.log(myObject);
but easily iterate an object using for ... in:
for(var key in myObject) {
if(myObject.hasOwnProperty(key)) {
myObject[key] *= 2;
}
}
check below code for your example.
class App extends React.Component {
constructor() {
super();
this.state = {
getCart: {
"70": [{
"numberPick": 13,
"numberPrice": 200
},
{
"numberPick": 44,
"numberPrice": 300
}
],
"81": [{
"numberPick": 31,
"numberPrice": 50
},
{
"numberPick": 22,
"numberPrice": 90
},
{
"numberPick": 38,
"numberPrice": 50
}
]
}
}
}
render() {
for (var k in this.state.getCart) {
// console.log(k);
this.state.getCart[k].map(i => {
// you want to get induvidual items
console.log('items : ', i);
console.log('numberPick : ', i['numberPick']);
console.log('numberPrice : ', i['numberPrice']);
})
}
return (
<div> check console log</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='root'></div>
You can loop through object:
for (var key in this.props.getCart) {
if (this.props.getCart.hasOwnProperty(key)) {
console.log(key + " -> " + this.props.getCart[key]);
this.props.getCart[key].map(item => {/*return items*/})
}
}
Then grab the array elements and push into another array.
How do I loop through or enumerate a JavaScript object?

Resources