A good[ish] website
Web development blog, loads of UI and JavaScript topics
I faced a completely thick problem when I was trying to filter a nested array object. I kept mutating the original variable, even though .map()
or .filter()
do not mutate the array they’re operating on.
More specifically I was generating tables from a array, and had a moment where I was sure I had discovered a bug JavaScript. That’s of course never the case, JavaScript worked as it should.
In the following code I tried to filter out the objects with green apples:
const tableData = [
{
title: 'Apples',
rows: [
{ name: 'Pink Lady', color: 'light red' },
{ name: 'Granny Smith', color: 'green' },
{ name: 'Red Delicious', color: 'red' }
]
}
// More fruit tables here...
]
// First map the tables
const filteredTable = tableData.map(data => {
// Filter the rows
const filteredColumns = data.rows.filter(row => {
return row.color.includes('red')
})
// Put the filtered data back into the shape
data.rows = filteredColumns
return data
})
// The original data will be mutated like the filtered data, this condition
// should evaluate `true`
const assert = JSON.stringify(tableData) === JSON.stringify(filteredTable)
window.alert(assert)
At a glance this should work, since tableData
is stored into a new variable as it’s being mapped and filtered. But, tableData
is 'magically' mutated to have the same shape as the filtered data.
The unwanted mutation happens because the object inside the array is edited. New object needs to be created inside the filter:
const filteredTable = tableData.map(data => {
const filteredColumns = data.rows.filter(row => {
return row.name.includes('red')
})
return { title: data.title, rows: filteredColumns }})
Or spread the data
, if that’s more convenient:
return {
...data,
rows: filteredColumns
}
Or use Object.assign()
, whatever is the best for your use-case:
return Object.assign({}, data, {
rows: filteredColumns
})
I was contemplating if this is blog-post-worthy at all, but hope this comes helpful to someone searching.
Thanks for reading!
Comments would go here, but the commenting system isn’t ready yet, sorry.