I have two states one has categories and the other has items.
all i need is one final state that combines both states, either by merging one
into the other or by making a third state.
the categories state looks like this:
{
category1: { items: [] },
category2: { items: [] }
}
and the second state is an array of items and it looks like this:
[
{"id": "1", itemInfo: { name: "itemName", category: "category1" }},
{"id": "2", itemInfo: { name: "itemName", category: "category1" }},
{"id": "3", itemInfo: { name: "itemName", category: "category2" }},
{"id": "4", itemInfo: { name: "itemName", category: "category1" }},
{"id": "5", itemInfo: { name: "itemName", category: "category2" }},
{"id": "6", itemInfo: { name: "itemName", category: "category2" }}
]
i need it to be like this:
{
category1: { items: [
{"id": "1", itemInfo: { name: "itemName", category: "category1" }},
{"id": "2", itemInfo: { name: "itemName", category: "category1" }},
{"id": "4", itemInfo: { name: "itemName", category: "category1" }}
]},
category2: { items: [
{"id": "3", itemInfo: { name: "itemName", category: "category2" }},
{"id": "5", itemInfo: { name: "itemName", category: "category2" }},
{"id": "6", itemInfo: { name: "itemName", category: "category2" }}
]}
}
help. please.
this is what i tried and didn’t work, it either duplicates the categories and i end up with 3 "category1" and 3 "category2" or the new items overwrite previous items.
const newFinalList = items.map((item: any) => {
return {[item.itemInfo.category]: {items: [item]}}
})
setFinalState((prevObj: any) => ({ ...prevObj, ...newFinalList }))
2
Answers
Issue
The issue is that the array mapping returns a new array, but you are wanting to map the array to the
categories
state shape which is an object. The mapping logic returns an object for each item element in the source array.Solution
Reduce the array into an object.
Example:
If you are using this to merge some passed props/context values, it is a React anti-pattern to also store this derived "state" into React state. Either compute and use the value directly, or use the
React.useMemo
hook to compute and provide a stable reference value.Drew nicely pointed out why your existing attempt doesn’t work. If you want to merge your first state (categories), so that it includes the items with the respective categories from your items state, then you can first make your items state a look-up map which maps the items category to the item object, and then map through your
categories
state by taking the entries of it and calling.map()
to added the items to each object. You can then callObject.fromEntries()
to convert it back into an object: