Render html table in React with dynamic array of objects - javascript

I have an array of objects that comes from an API, but the content of this array is dynamic.
I want to map this data to an HTML table in React, using the array.map function, but I don't know how I could access the variable.property.
For example:
{
array.map(data=> {
<td>{data.DynamicProperty}</td>
})
}
What should I put in DynamicProperty ?
Could anybody show to me what could be the better approach for this case?

You can simply get all values within object using Object.values and then map over them to return table columns in case you have more than one keys in each object. Or you could simply return <td>{Object.values(data)[0]}</td> if you have only one key in each object
{
array.map(data=> {
return (
<>
{Object.values(data).map(val => <td>{data}</td>)}
</>
)
})
}

Since the data is dynamic, what I had to do was take the property names and storing in the component hook's state:
const [mappableFields, setMappableFields] = useState([]);
useEffect(() => {
if (array && array.length > 0) {
setMappableFields(Object.getOwnPropertyNames(array[0]));
}
}, [array]);
Then I mapped the array and the mappableFields, creating the <td> by reading each data by it's key, like this:
{ array.map((data, index) => (
<tr key={index}>
{
mappableFields.map((header, idx) => (
<td key={idx}>{data[header]}</td>
))
}
</tr>
))
}

Related

Filter in react.js

I'm trying to make a filter of all my "localtypes" but when I check the console on my browser it shows me an empty array. I want to get to the localtypes propertys of the API I'm using
I tried to use this filter
const type = (category) => {
const clonArray = [...restaurants]
const filter = clonArray.filter((restaurant) => {
return restaurant.localtype == category;
})
setRestaurants(filter);
}
sending the props to another component "Filter" as
categories={() => type()}
but when i get to these props in the Filter component i get an empty array
onClick={() => {categories("farmacia")}}>
I want to know how to access to the props of "categories"
You can do it in below order. First thing to note is that .filter does not mutate the original array, so you can use it directly.
You need to pass the value with function to the Filter component.
onClick={() => categories('farmacia'}
categories={(cat) => type(cat)}
const type = (category) => {
const filter = clonArray.filter((restaurant) => {
return restaurant.localtype === category;
})
setRestaurants(filter);
}

Antdesign table not rerendering on new column values

I am having trouble rerendering the columns of my table, the library i am using is ant design and I am trying to create a feature where I reorder the column of the table on demand.
I have created an example the issue here: https://replit.com/#coupacoupa/Ant-Design-column-reordering
In the example, I created a simple button that changes the order of the column which changes a div showcasing the state changed, but in the ant design table, the column doesn't change.
Below is a snipplet of the way I change the state
export default ({ columnOrder, data }: IProps) => {
const [orderedColumn, setOrderedColumn] = useState<ColumnsType<ISomeTableColumns>>(columns);
useEffect(() => {
console.log('columnOrder', columnOrder);
const sortArray = columns.sort((a, b) => {
return (
columnOrder.findIndex((x) => x.text === a.title) -
columnOrder.findIndex((x) => x.text === b.title)
);
});
if (sortArray) {
setOrderedColumn(sortArray);
}
}, [columnOrder]);
return <>
<Table
columns={orderedColumn}
dataSource={data}
bordered
size="middle"
scroll={{ x: 'calc(700px + 50%)' }}
/>
<h2>Value Of ordered Columns</h2>
<div>{JSON.stringify(orderedColumn)}</div>
</>
};
The sort() method sorts the elements of an array in place and returns the reference to the same array, now sorted. But you should pass a new array into setOrderedColumn to rerender
useEffect(() => {
console.log('columnOrder', columnOrder);
columns.sort((a, b) => {
return (
columnOrder.findIndex((x) => x.text === a.title) -
columnOrder.findIndex((x) => x.text === b.title)
);
});
if (columns) {
setOrderedColumn([...columns]);
}
}, [columnOrder, columns]);

How to return a tag from a method in react js?

I want to return a tag from a method so that once I call the method the tags are returned and these tags are used to call a component.
const Populate =() =>
{
let tags = [];
analysisinfo.forEach((_item,index) =>
{
if(analysisinfo[index].id!== defaultid)
tags.push(<AU props={analysisinfo[index]} instance ={index}/>);
console.log({tags});
}
return tags;
let me explain in-detail the analysisinfo is an useState array which contains the below values. These values are being passed into this method.
0:
cpu: true
hdd: true
id: "00000000000000000000000000000000"
ram: true
And pushes these values into tags[]. I want them pushed into array in the form of a <>, so that when I return it calls the <AU..../> tag component which takes the above values as props.
Use a combination of filter and map:
const Populate = () => (
<>
{
analysisinfo
.filter(i => i.id !== defaultid)
.map((i, idx) => (
<AU props={i} instance={idx} />
))
}
</>
);

How can I assign unique IDs to DIVs generated from multidimensional array located in state of a react component?

I have a multidimentional array, based on the hirerchy of the array elements, I want to created exactly the same multilevel nested DIVs in React app. How can I assign unique IDs to DIVs generated from multidimensional array in React Component state so that whenever I click on particular div I should know which element of this multidimentional array needs to modified.
Following is the code I have written in to render DIVs as per Array located in component's state:
state = {
arrSectionsContainer: [
['A'],
[
[
['D'], ['E']
],
['C']
]
]
}
Function to render UI (UI is correctly rendered):
render() {
const { arrSectionsContainer } = this.state;
const renderUI = (arrSectionsContainer, j) => {
return (
arrSectionsContainer.map((ele, i) => {
if (ele.length === 1) {
return (
<div id={`sectionDiv${i}${j}`}>Single Div - {i}</div>
)
} else {
return (
<div>
{renderUI(ele, i)}
</div>
)
renderUI(ele)
}
})
)
}
return (
<div>
{renderUI(arrSectionsContainer, 0)}
</div>
)
}

Immutable .toArray() wont render data - ReactJS

I am mapping over some data and I am trying to use some of the data as the options for the semantic-ui-react Dropdown component, but the data wont load in even if I add .toArray() to the end of it, however if I change the data structure to not use Immutable, it works fine. I mainly wanted to understand why so I could get a better understanding of things.
Here is the mapping of the data with immutable:
{
labelingData.map((item, i) => {
return (
<span key={i}>
{
item.get('categories').map((category, c) => {
return (
<span key={c}>
{
category.get('subcategories').map((subcategory, sc) => {
return (
<span key={sc}>
{
subcategory.get('name') === 'Labels'
? <Dropdown
defaultValue={'Bananas'}
options={subcategory.get('childItems').toArray()}
/>
: null
}
</span>
);
})
}
</span>
);
})
}
</span>
);
})
}
I do get an error in the console about unknown props but I am not adding these props in my code:
Unknown props `_root`, `__ownerID`, `__hash`, `__altered` on <div> tag. Remove these props from the element
The api of semantic-ui-react Dropdown options is to pass in an array of objects that look like:
{ text: '', value: '' }
However, when you call .toArray() on a Immutable.List containing some Immutable.Map it will not .toJS() the Maps.
eg.
var list = Immutable.fromJS({ value: 1 }, 2]);
console.log(list.toArray()); // prints [Immutable.Map, 2]
So you are actually giving Dropdown an array of Maps and the Dropdown doesn't use .get to get the values from the object.
Another thing is that React prefers to receive arrays rather than immutable.Lists.
So you could use a reduce function rather than a map function to create a normal array of react components:
item.get('categories').reduce((result, category, c) => {
result.push(<Category key={c} category={category} />);
return result;
}, []);

Categories