如何修复我的过滤器中的这个 ESlint (no-param-reassign) 错误
How to fix this ESlint (no-param-reassign) error in my Filter
我试图只查找拥有特定服务的用户。每个用户都有一系列服务。我需要找到的匹配项如下:
userService.name === service.name && !user.disabled
下面的代码有效,但在处理参数重新分配时出现 ESlint 错误。
export const matchUserWithService = (user, userService, service) => {
if (userService.name === service.name && !user.disabled) {
user.isMatched = true;
userService.rights = service.rights;
}
return userService;
};
export const renderServiceAdmins = (users, selectedService) => {
const usersWithService = users.filter((user) => {
user.services.map(usrSrv => matchUserWithService(user, usrSrv, selectedService));
if (user.isMatched) return user;
return false;
});
return usersWithService.map(user => user.services.map(service => service.rights.map((right) => {
if (
service.name === selectedService.name &&
lowCase(right.name) === 'admin' &&
!right.disabled
) {
return (
<li key={user.email + randId()}>
{ user.name } | <span className="info_blue">{ user.email }</span>
</li>
);
}
return null;
})));
};
这可以用 .find
重构吗?
您的代码是有效的,但是 as the rule points out,修改或重新分配函数参数可能会导致意外行为。
通常,如果您不想在 .eslintrc
文件中完全禁用规则,而只想抑制特定的 eslint 错误发生,请使用 rule-disabling comments 之一,这也有点表明您知道自己在做什么。
也许您可以在不禁用规则的情况下重写?
export const renderServiceAdmins = (users, selectedService) => {
var admins = users.reduce((serviceAdmins, user) => {
user.services
.forEach((service) =>{
if(service.name === selectedService.name) {
service.rights
.forEach((right)=> {
if( lowCase(right.name) === 'admin' && !right.disabled) {
serviceAdmins.concat[{
name: user.name,
name: user.email
}]
}
})
}
});
return serviceAdmins;
}, []);
return admins.map(admin=> {
return (
<li key={admin.email + randId()}>
{ admin.name } | <span className="info_blue">{ admin.email }</span>
</li>
);
});
};
我建议重构代码,因为现在它依赖于 .map
调用内部的突变,这可能变得很难推理。我无法检查我建议的代码是否真的有效,但我认为它更清楚地表达了你想要做的事情的意图。
编辑。解释:简而言之,我们有一个用户列表,其中只有一些是相关的。这告诉我们我们可能希望代码以 users.filter
开头。一般的想法是过滤掉对所选服务具有管理员权限的用户。因此,我尝试将该逻辑提取到一个函数 (userHasAdminRightsForService
) 中,我将其实现为 returns 我们将要用来过滤用户的函数。由于这种设计,我们得到的代码读起来更像普通英语:users.filter(userHasAdminRightsForService(selectedService))
而不是 users.filter(user => userHasAdminRightsForService(user, selectedService))
.
Array.prototype.some
用于检查数组是否至少有一个元素满足某些条件。所以像 userService.rights.some(right => lowCase(right.name) === 'admin')
这样的行意味着我们检查 userService.rights
中的至少一个权限是否满足它应该具有名称 'admin'.
的标准
// given a serviceToCheckFor, return a function that checks if
// one specific user has any userService, with admin rights, that match the name of serviceToCheckFor
export const userHasAdminRightsForService = serviceToCheckFor = user => {
return user.services.some(userService =>
// name check
userService.name === serviceToCheckFor.name &&
// check if there exists a non-disabled admin right
userService.rights
.filter(right => !right.disabled)
.some(right => lowCase(right.name) === 'admin')
);
};
export const renderServiceAdmins = (users, selectedService) => {
const adminsForSelectedService = users
.filter(user => !user.disabled)
.filter(userHasAdminRightsForService(selectedService))
return adminsForSelectedService.map( admin =>
(<li key={admin.email + randId()}>
{ admin.name } | <span className="info_blue">{ admin.email }</span>
</li>)
);
};
我们最终以这种方式解决了它,更简洁,代码也更少(删除了 2 个函数)!
缺少的部分是链接过滤器然后使用 .find
export const renderServiceAdmins = (users, theService) =>
users
.filter(user => !user.disabled)
.filter(user => user.services.find(
usrSrv => (
usrSrv.name === theService.name &&
usrSrv.rights.find(r => r.name.toLowerCase() === 'admin' && !r.disabled)
)
))
.map(user => (
<li key={user.email + randId()}>
{ user.name } | <span className="info_blue">{ user.email }</span>
</li>
));
我试图只查找拥有特定服务的用户。每个用户都有一系列服务。我需要找到的匹配项如下:
userService.name === service.name && !user.disabled
下面的代码有效,但在处理参数重新分配时出现 ESlint 错误。
export const matchUserWithService = (user, userService, service) => {
if (userService.name === service.name && !user.disabled) {
user.isMatched = true;
userService.rights = service.rights;
}
return userService;
};
export const renderServiceAdmins = (users, selectedService) => {
const usersWithService = users.filter((user) => {
user.services.map(usrSrv => matchUserWithService(user, usrSrv, selectedService));
if (user.isMatched) return user;
return false;
});
return usersWithService.map(user => user.services.map(service => service.rights.map((right) => {
if (
service.name === selectedService.name &&
lowCase(right.name) === 'admin' &&
!right.disabled
) {
return (
<li key={user.email + randId()}>
{ user.name } | <span className="info_blue">{ user.email }</span>
</li>
);
}
return null;
})));
};
这可以用 .find
重构吗?
您的代码是有效的,但是 as the rule points out,修改或重新分配函数参数可能会导致意外行为。
通常,如果您不想在 .eslintrc
文件中完全禁用规则,而只想抑制特定的 eslint 错误发生,请使用 rule-disabling comments 之一,这也有点表明您知道自己在做什么。
也许您可以在不禁用规则的情况下重写?
export const renderServiceAdmins = (users, selectedService) => {
var admins = users.reduce((serviceAdmins, user) => {
user.services
.forEach((service) =>{
if(service.name === selectedService.name) {
service.rights
.forEach((right)=> {
if( lowCase(right.name) === 'admin' && !right.disabled) {
serviceAdmins.concat[{
name: user.name,
name: user.email
}]
}
})
}
});
return serviceAdmins;
}, []);
return admins.map(admin=> {
return (
<li key={admin.email + randId()}>
{ admin.name } | <span className="info_blue">{ admin.email }</span>
</li>
);
});
};
我建议重构代码,因为现在它依赖于 .map
调用内部的突变,这可能变得很难推理。我无法检查我建议的代码是否真的有效,但我认为它更清楚地表达了你想要做的事情的意图。
编辑。解释:简而言之,我们有一个用户列表,其中只有一些是相关的。这告诉我们我们可能希望代码以 users.filter
开头。一般的想法是过滤掉对所选服务具有管理员权限的用户。因此,我尝试将该逻辑提取到一个函数 (userHasAdminRightsForService
) 中,我将其实现为 returns 我们将要用来过滤用户的函数。由于这种设计,我们得到的代码读起来更像普通英语:users.filter(userHasAdminRightsForService(selectedService))
而不是 users.filter(user => userHasAdminRightsForService(user, selectedService))
.
Array.prototype.some
用于检查数组是否至少有一个元素满足某些条件。所以像 userService.rights.some(right => lowCase(right.name) === 'admin')
这样的行意味着我们检查 userService.rights
中的至少一个权限是否满足它应该具有名称 'admin'.
// given a serviceToCheckFor, return a function that checks if
// one specific user has any userService, with admin rights, that match the name of serviceToCheckFor
export const userHasAdminRightsForService = serviceToCheckFor = user => {
return user.services.some(userService =>
// name check
userService.name === serviceToCheckFor.name &&
// check if there exists a non-disabled admin right
userService.rights
.filter(right => !right.disabled)
.some(right => lowCase(right.name) === 'admin')
);
};
export const renderServiceAdmins = (users, selectedService) => {
const adminsForSelectedService = users
.filter(user => !user.disabled)
.filter(userHasAdminRightsForService(selectedService))
return adminsForSelectedService.map( admin =>
(<li key={admin.email + randId()}>
{ admin.name } | <span className="info_blue">{ admin.email }</span>
</li>)
);
};
我们最终以这种方式解决了它,更简洁,代码也更少(删除了 2 个函数)!
缺少的部分是链接过滤器然后使用 .find
export const renderServiceAdmins = (users, theService) =>
users
.filter(user => !user.disabled)
.filter(user => user.services.find(
usrSrv => (
usrSrv.name === theService.name &&
usrSrv.rights.find(r => r.name.toLowerCase() === 'admin' && !r.disabled)
)
))
.map(user => (
<li key={user.email + randId()}>
{ user.name } | <span className="info_blue">{ user.email }</span>
</li>
));