I got a schema object that looks like this:
const schema = {
social: {
facebook: 'someValue',
twitter: {
department: {
departmentImage: {
editable: 'someValue'
}
}
}
}
};
The editable
property indicates a value that I want to edit, and may appear in several nested locations in the object.
My approach to edit it is to recursively create a new object who is an exact copy of the original, and populate a new value where I encounter editable
.
Like this:
const formatSchema = (schema, data, formattedSchema = {}) => {
for (const schemaKey in schema) {
const firstKey = Object.keys(schema[schemaKey])[0];
if (schema[schemaKey] instanceof Object) {
formattedSchema[schemaKey] = schema[schemaKey];
formatschema(schema[schemaKey], data, formattedSchema[schemaKey]);
}
if (schema[schemaKey] instanceof Object && firstKey === 'editable') {
*replacing data logic*
formattedSchema[schemaKey] = ...*replacingData*;
formatschema(schema[schemaKey], data, formattedSchema[schemaKey]);
} else {
formattedSchema[schemaKey] = schema[schemaKey];
}
}
return formattedSchema;
};
But I feel this solution may be inefficient as I create every single bit of the object from scratch and this would happen thousands of times a day.
Is there a way to do it better?
CodePudding user response:
Here's a recursive immutable update
that works for any native input type. Don't worry about performance here as it's plenty fast, even if your object has thousands of fields. Let me know how this suits you and I can make a change if it's needed -
function update(t, func) {
switch (t?.constructor) {
case Object:
return Object.fromEntries(
Object.entries(t).map(([k,v]) =>
[k, func([k, update(v, func)])]
)
)
case Array:
return t.map((v, k) => func([k, update(v, func)]))
default:
return func([null, t])
}
}
const schema = {
social: {
facebook: 'someValue',
twitter: {
department: {
departmentImage: {
editable: 'someValue'
}
},
someArr: [{ editable: 1 }, { editable: 2 }, { hello: "world" }]
},
}
}
console.log(update(schema, ([k,v]) =>
k == "editable" ? "✅" : v
))
.as-console-wrapper {min-height: 100% !important; top: 0}
{
"social": {
"facebook": "someValue",
"twitter": {
"department": {
"departmentImage": {
"editable": "✅"
}
},
"someArr": [
{
"editable": "✅"
},
{
"editable": "✅"
},
{
"hello": "world"
}
]
}
}
}