У меня есть массив объектов с многоуровневой вложенностью.
const switches = [{
orgId: "1111a7cd-0d58-11ef-83a2-06a19a0b1f5d",
orgName: "Management 1",
orgType: 2,
organisations: [],
features: [{
name: "AdvancedAdminApprovalLevels",
type: "feature",
category: "Management Features",
value: false,
}, {
name: "AdminCategoryApprovalByRole",
type: "feature",
category: "Management Features",
value: false,
}],
}, {
orgId: "2222a7cd-0d58-11ef-83a2-06a19a0b1f5d",
orgName: "Management 2",
orgType: 2,
organisations: [{
orgId: "33333f59a-4976-11ed-af5d-021feb88a3f6",
orgName: "Submanagement ",
orgType: 2,
features: [{
name: "AdvancedAdminApprovalLevels",
type: "feature",
category: "Management Features",
value: false,
}, {
name: "AdminCategoryApprovalByRole",
type: "feature",
category: "Management Features",
value: false,
}],
}],
features: [{
name: "AdvancedAdminApprovalLevels",
type: "feature",
category: "Management Features",
value: false,
}, {
name: "AdminCategoryApprovalByRole",
type: "feature",
category: "Management Features",
value: false,
}],
}, {
orgId: "4444a7cd-0d58-11ef-83a2-06a19a0b1f5d",
orgName: "Management 3",
orgType: 2,
organisations: [],
features: [{
name: "AdvancedAdminApprovalLevels",
type: "feature",
category: "Management Features",
value: false,
}, {
name: "AdminCategoryApprovalByRole",
type: "feature",
category: "Management Features",
value: false,
}],
}];
Мне нужна функция, которая сопоставляет ее с новым массивом, где, если строка, указанная === name в объектах массива функций, тогда значение должно быть изменено на значение, указанное в параметре.
Итак, если я вызову функцию типа
handleTopLevelToggle('AdvancedAdminApprovalLevels', true);
Я должен вернуть те же вложенные массивы, но со значением, измененным на true для всех с именем «AdvancedAdminApprovalLevels» на всех вложенных уровнях.
Решение, с которого я начал, было
const handleTopLevelToggle = (value, fSwitch) => {
const mappedArray = switches.map((swtch) => {
swtch.features.map((feature) => {
if (feature.name === fSwitch) {
return { ...swtch, value: value };
}
return swtch;
});
});
return mappedArray;
};



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Ваше текущее решение находится на правильном пути, но у него есть несколько проблем.
Пересмотренная функция:
const handleTopLevelToggle = (fSwitch: string, value: boolean) => {
const mapFeatures = (features) => {
return features.map((feature) => {
if (feature.name === fSwitch) {
return { ...feature, value: value };
}
return feature;
});
};
const mapOrganisations = (organisations) => {
return organisations.map((org) => {
return { ...org, features: mapFeatures(org.features) };
});
};
const mappedArray = switches.map((swtch) => {
return {
...swtch,
features: mapFeatures(swtch.features),
organisations: mapOrganisations(swtch.organisations),
};
});
return mappedArray;
};
Вам просто нужна простая рекурсивная функция:
const handleTopLevelToggle = (data, name, value) => {
const toggle = (organisations) => organisations?.map((o) => ({
...o,
features: o.features.map((f) => ({
...f,
value: f.name === name ? value : f.value
})),
organisations: toggle(o.organisations)
}));
return toggle(data);
};
Полный фрагмент:
const switches = [
{
orgId: "1111a7cd-0d58-11ef-83a2-06a19a0b1f5d",
orgName: "Management 1",
orgType: 2,
organisations: [],
features: [
{
name: "AdvancedAdminApprovalLevels",
type: "feature",
category: "Management Features",
value: false,
},
{
name: "AdminCategoryApprovalByRole",
type: "feature",
category: "Management Features",
value: false,
},
],
},
{
orgId: "2222a7cd-0d58-11ef-83a2-06a19a0b1f5d",
orgName: "Management 2",
orgType: 2,
organisations: [
{
orgId: "33333f59a-4976-11ed-af5d-021feb88a3f6",
orgName: "Submanagement ",
orgType: 2,
features: [
{
name: "AdvancedAdminApprovalLevels",
type: "feature",
category: "Management Features",
value: false,
},
{
name: "AdminCategoryApprovalByRole",
type: "feature",
category: "Management Features",
value: false,
},
],
},
],
features: [
{
name: "AdvancedAdminApprovalLevels",
type: "feature",
category: "Management Features",
value: false,
},
{
name: "AdminCategoryApprovalByRole",
type: "feature",
category: "Management Features",
value: false,
},
],
},
{
orgId: "4444a7cd-0d58-11ef-83a2-06a19a0b1f5d",
orgName: "Management 3",
orgType: 2,
organisations: [],
features: [
{
name: "AdvancedAdminApprovalLevels",
type: "feature",
category: "Management Features",
value: false,
},
{
name: "AdminCategoryApprovalByRole",
type: "feature",
category: "Management Features",
value: false,
},
],
},
];
const handleTopLevelToggle = (data, name, value) => {
const toggle = (organisations) => organisations?.map((o) => ({
...o,
features: o.features.map((f) => ({
...f,
value: f.name === name ? value : f.value
})),
organisations: toggle(o.organisations)
}));
return toggle(data);
};
console.info(handleTopLevelToggle(switches, 'AdvancedAdminApprovalLevels', true));Вы можете использовать рекурсивный подход и рассматривать массивы как значения.
const
switches = [{ orgId: "1111a7cd-0d58-11ef-83a2-06a19a0b1f5d", orgName: "Management 1", orgType: 2, organisations: [], features: [{ name: "AdvancedAdminApprovalLevels", type: "feature", category: "Management Features", value: false }, { name: "AdminCategoryApprovalByRole", type: "feature", category: "Management Features", value: false }] }, { orgId: "2222a7cd-0d58-11ef-83a2-06a19a0b1f5d", orgName: "Management 2", orgType: 2, organisations: [{ orgId: "33333f59a-4976-11ed-af5d-021feb88a3f6", orgName: "Submanagement ", orgType: 2, features: [{ name: "AdvancedAdminApprovalLevels", type: "feature", category: "Management Features", value: false }, { name: "AdminCategoryApprovalByRole", type: "feature", category: "Management Features", value: false }] }], features: [{ name: "AdvancedAdminApprovalLevels", type: "feature", category: "Management Features", value: false }, { name: "AdminCategoryApprovalByRole", type: "feature", category: "Management Features", value: false }] }, { orgId: "4444a7cd-0d58-11ef-83a2-06a19a0b1f5d", orgName: "Management 3", orgType: 2, organisations: [], features: [{ name: "AdvancedAdminApprovalLevels", type: "feature", category: "Management Features", value: false }, { name: "AdminCategoryApprovalByRole", type: "feature", category: "Management Features", value: false }] }],
change = (array, name, value) => array.map(object => Object.fromEntries(Object
.entries(object)
.map(([k, v]) => [
k,
Array.isArray(v)
? change(v, name, value)
: k === 'value' && object.name === name
? value
: v
])
)),
result = change(switches, 'AdvancedAdminApprovalLevels', true);
console.info(result);.as-console-wrapper { max-height: 100% !important; top: 0; }В зависимости от того, что необходимо изменить, решение будет разным. Например. для неглубокого изменения (все ссылки на объекты останутся прежними) вы можете использовать
function changeAllFor(object:any, key:string,value:any){
if (!object)return;
if (Array.isArray(object)){
for(let i = 0; i < object.length; i++){
changeAllFor(object[i], key, value);
}
return;
}
if (typeof object !== 'object')return;
const keys = Object.keys(object);
for(let i = 0; i < keys.length; i++){
if (keys[i] === key){
object[keys[i]] = value;
}
if (typeof object[keys[i]] === 'object'){
changeAllFor(object[keys[i]], key, value);
}
}
}
Если вам нужны новые ссылки на объекты (например, для сравнения на уровне объекта), я бы выбрал:
function createNewFor(object,key,value){
if (!object)return object; //undefined or null
if (Array.isArray(object)){
return object.map((item) => createNewFor(item, key, value));
}
if (typeof object !== 'object')return object;
const keys = Object.keys(object);
const newObject = {...object};
for(let i = 0; i < keys.length; i++){
if (keys[i] === key){
newObject[keys[i]] = value;
}else{
newObject[keys[i]] = createNewFor(object[keys[i]], key, value);
}
}
}
Это самое интуитивное решение из всех. Спасибо.