I have the following where it will display items in a certain way.
import './App.css'
import _ from 'lodash'
const App = () => {
const dataone = [
{ id: 1, month: 'jan', level: 8, clazz_id: '1A' },
{ id: 2, month: 'feb', level: 6, clazz_id: '1A' },
{ id: 3, month: 'jan', level: 2, clazz_id: '2B' },
{ id: 4, month: 'feb', level: 3, clazz_id: '2B' },
{ id: 5, month: 'mar', level: 5, clazz_id: '2B' },
]
const data = _.groupBy(dataone, 'clazz_id')
const entries = Object.entries(data)
return (
<div className='App'>
{entries.map((item, index) => (
<div>
<h2>{item[0]}</h2>
<h2>
{item[1].map((e) => (
<p>
{e.month}
{'--'}
{e.level}
</p>
))}
</h2>
</div>
))}
</div>
)
}
export default App
The above code will display the array of objects like below:
1A
jan-8
feb-6
2B
jan-2
feb-3
mar-5
This is what I want however the above code is done with lodash and object.entries and so I am looking for a better and clearner solution.
CodePudding user response:
This is achievable using only the Javascript builtins (Array.reduce, Array.map, and Object.entries). Better to avoid using lodash
as it will add up to the bundle size of your web app and make the app slower when loading.
I would do it like below.
const App = () => {
const dataone = [
{ id: 1, month: "jan", level: 8, clazz_id: "1A" },
{ id: 2, month: "feb", level: 6, clazz_id: "1A" },
{ id: 3, month: "jan", level: 2, clazz_id: "2B" },
{ id: 4, month: "feb", level: 3, clazz_id: "2B" },
{ id: 5, month: "mar", level: 5, clazz_id: "2B" }
];
return (
<div className="App">
{Object.entries(
dataone.reduce((prev, curr) => {
prev[curr.clazz_id]
? prev[curr.clazz_id].push(curr)
: (prev[curr.clazz_id] = [curr]);
return prev;
}, {})
).map(([key, value]) => {
return (
<div>
<h2>{key}</h2>
<h2>
{value.map(({ level, month }) => (
<p>
{month}
{"--"}
{level}
</p>
))}
</h2>
</div>
);
})}
</div>
);
};
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
CodePudding user response:
You can use reduce
to group by the data in the required format
export default function App() {
const dataone = [
{ id: 1, month: 'jan', level: 8, clazz_id: '1A' },
{ id: 2, month: 'feb', level: 6, clazz_id: '1A' },
{ id: 3, month: 'jan', level: 2, clazz_id: '2B' },
{ id: 4, month: 'feb', level: 3, clazz_id: '2B' },
{ id: 5, month: 'mar', level: 5, clazz_id: '2B' },
];
function groupByClass(arr) {
return arr.reduce((acc, curr) => {
if (!acc[curr.clazz_id]) {
acc[curr.clazz_id] = {
classId: curr.clazz_id,
level: [`${curr.month}-${curr.level}`],
};
} else {
acc[curr.clazz_id].level.push(`${curr.month}-${curr.level}`);
}
return acc;
}, {});
}
const groupedData = groupByClass(dataone);
console.log(groupedData);
return (
<div className="App">
{Object.keys(groupedData).map((item) => {
return (
<div>
<div>{groupedData[item].classId}</div>
{groupedData[item].level.map((elem) => {
return <p>{elem}</p>;
})}
</div>
);
})}
</div>
);
}
CodePudding user response:
Lodash, also has a .map
method that can iterate over objects as well. So, you could use that for consistency.
const App = () => {
const dataone = [
{ id: 1, month: 'jan', level: 8, clazz_id: '1A' },
{ id: 2, month: 'feb', level: 6, clazz_id: '1A' },
{ id: 3, month: 'jan', level: 2, clazz_id: '2B' },
{ id: 4, month: 'feb', level: 3, clazz_id: '2B' },
{ id: 5, month: 'mar', level: 5, clazz_id: '2B' },
]
const data = _.groupBy(dataone, 'clazz_id')
return (
<div className='App'>
{_.map(data,(value, key) => (
<div>
<h2>{key}</h2>
<h2>
{value.map((e) => (
<p>
{e.month}
{'--'}
{e.level}
</p>
))}
</h2>
</div>
))}
</div>
)
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<div id="root"></div>