我目前已经按角色ID对api数据进行了代码转换。然而,我需要显示另一个视图,该视图将根据用户所在的项目ID对数据进行分组
我可以简单地复制粘贴并创建另一个用于projectId数据转换的方法,但是,我觉得我的方法可能很混乱,不容易重复使用。所以我想问一下,是否有更好的方法可以做到这一点?
因为我不能简单地通过在函数中重用的变量中放入rolesId或projectId来将函数中的roleId交换为projectId。
有人能帮我吗?
用于在ant设计树数据表中显示api数据转换的代码:
let apiData = [
{
email: "alyssayo@xxx.com",
permissionIds: null,
roleIds: ["raa", "baa", "caa"],
projectIds: ["1aa", "3aa"]
},
{
email: "chiuewww@xxx.com",
permissionIds: null,
roleIds: ["baa", "caa"],
projectIds: ["1aa", "2aa", "3aa"]
},
{
email: "lalaqq@xxx.com",
permissionIds: null,
roleIds: ["caa"],
projectIds: ["1aa"]
},
{
email: "sqssq@xxx.com",
permissionIds: null,
roleIds: [],
projectIds: []
}
];
//Isolate and transform data by roleId
const transData = apiData.reduce((arr, item) => {
let formatted = item.roleIds.map((id) => {
return {
roleIds: id,
children: [{ ...item, roleIds: id }]
};
});
return [...arr, ...formatted];
}, []);
//Group transformed data by roleIds
const findMatch = (arr, roleIds) =>
arr.find((item) => item.roleIds === roleIds);
const groupArray = (originalArr) => {
return Array.isArray(originalArr)
? originalArr.reduce((previousObj, obj) => {
if (findMatch(previousObj, obj.roleIds)) {
findMatch(previousObj, obj.roleIds).children.push(...obj.children);
} else {
previousObj.push(obj);
}
return previousObj;
}, [])
: "Need an array";
};
//Call the group roleId function on transformed data by roleId
const userRoledata = groupArray(transData);
//Add key to parent and children
let key = 1;
userRoledata.forEach((item) => {
item.key = key++;
item.children.forEach((child) => {
child.key = key++;
});
});
setData(userRoledata); //this will be dataSource for table rendering in ant design
在蚂蚁设计中用作数据源时,转换后的数据将显示什么:
如果按角色ID分组:
[
{
"roleIds": "raa",
"children": [
{
"email": "alyssayo@xxx.com",
"permissionIds": null,
"roleIds": "raa",
"projectIds": [
"1aa",
"3aa"
],
"key": 2
}
],
"key": 1
},
{
"roleIds": "baa",
"children": [
{
"email": "alyssayo@xxx.com",
"permissionIds": null,
"roleIds": "baa",
"projectIds": [
"1aa",
"3aa"
],
"key": 4
},
{
"email": "chiuewww@xxx.com",
"permissionIds": null,
"roleIds": "baa",
"projectIds": [
"1aa",
"2aa",
"3aa"
],
"key": 5
}
],
"key": 3
},
{
"roleIds": "caa",
"children": [
{
"email": "alyssayo@xxx.com",
"permissionIds": null,
"roleIds": "caa",
"projectIds": [
"1aa",
"3aa"
],
"key": 7
},
{
"email": "chiuewww@xxx.com",
"permissionIds": null,
"roleIds": "caa",
"projectIds": [
"1aa",
"2aa",
"3aa"
],
"key": 8
},
{
"email": "lalaqq@xxx.com",
"permissionIds": null,
"roleIds": "caa",
"projectIds": [
"1aa"
],
"key": 9
}
],
"key": 6
}
]
如果按项目ID分组:
[
{
"projectIds": "1aa",
"children": [
{
"email": "alyssayo@xxx.com",
"permissionIds": null,
"roleIds": [
"raa",
"baa",
"caa"
],
"projectIds": "1aa",
"key": 2
},
{
"email": "chiuewww@xxx.com",
"permissionIds": null,
"roleIds": [
"baa",
"caa"
],
"projectIds": "1aa",
"key": 3
},
{
"email": "lalaqq@xxx.com",
"permissionIds": null,
"roleIds": [
"caa"
],
"projectIds": "1aa",
"key": 4
}
],
"key": 1
},
{
"projectIds": "3aa",
"children": [
{
"email": "alyssayo@xxx.com",
"permissionIds": null,
"roleIds": [
"raa",
"baa",
"caa"
],
"projectIds": "3aa",
"key": 6
},
{
"email": "chiuewww@xxx.com",
"permissionIds": null,
"roleIds": [
"baa",
"caa"
],
"projectIds": "3aa",
"key": 7
}
],
"key": 5
},
{
"projectIds": "2aa",
"children": [
{
"email": "chiuewww@xxx.com",
"permissionIds": null,
"roleIds": [
"baa",
"caa"
],
"projectIds": "2aa",
"key": 9
}
],
"key": 8
}
]
定义一个具有2个参数的transform
函数。首先是apiData
,它是要转换的数据,其次是transformation_key
,它是roleIds
或projectIds
的字符串。
在这个函数中,您首先要生成一个以不同的roleIds/projectId作为键的对象,并为每个键生成一个包含所有项的数组。
要做到这一点,你可以使用一个减速器和循环项目
apiData.reduce((obj, item) => {
if (!item[transformation_key]) return obj; // in case item[transformation_key] is null, you can skip the item an just return the item as is.
... // if not, we've to reduce over the array of roleIds/projectIds within the item as well.
}, {}) // {} is the new object (`obj` refers to this within the reducer)
在每个项目中,我们还必须循环该项目的roleIds/projectId中的所有项目,因此我们添加了第二个/内部减速器。
// item[transformation_key] is the array of roleIds/projectIds within your item.
item[transformation_key].reduce((cur, id) => {
// `cur` is actually the same object as the `obj` from the outer reducer.
if (!cur[id]) cur[id] = [] // if the key/id doesn't excist yet on the object, we set it equal to an empty array.
cur[id].push({
...item,
[transformation_key]: id
}) // we push the item to the array (using the spread operator and updating the value for the `transformation_key` within the item.
return cur // you must return the object `cur`.
}, obj) // we pass to `obj` from the outer reducer into the inner reducer.
这将生成类似的对象
const transformedObject = {
[roleIds/projectIds] : [
... all the children
]
}
接下来,我们将id映射到所需的输出
return Object.keys(transformedObject).map(key => {
return {
[transformation_key]: key,
children: transformedObject[key]
}
})
总结
function transform(apiData, transformation_key) {
if (!(transformation_key == 'roleIds' || transformation_key == 'projectIds')) throw new Error("Choose either 'roleIds' or 'projectIds' as a transformation_key")
const transformedObject = apiData
.reduce((obj, item) => {
if (!item[transformation_key]) return obj;
return item[transformation_key].reduce((cur, id) => {
if (!cur[id]) cur[id] = []
cur[id].push({
...item,
[transformation_key]: id
})
return cur
}, obj)
}, {});
return Object.keys(transformedObject).map(key => {
return {
[transformation_key]: key,
children: transformedObject[key]
}
})
}
const transDataByRoleIds = transform(res.data, 'roleIds')
const transDataByProjectIds = transform(res.data, 'projectIds')