Как исправить эту ошибку ESlint (no-param-reassign) в моем фильтре
Я пытаюсь найти только пользователей, у которых есть определенный сервис. У каждого пользователя есть массив Сервисов. И матч, который мне нужно найти, следующий:
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
?
4 ответа
Я бы предложил реструктурировать код, потому что теперь он зависит от мутаций внутри .map
звонить, что может быть довольно сложно рассуждать. Я не могу проверить, что мой предложенный код действительно работает, но я думаю, что он выражает намерение того, что вы пытаетесь сделать более четко.
Редактировать Пояснение: Короче, у нас есть список пользователей, для которых актуальны только некоторые. Это говорит нам о том, что мы, вероятно, хотели бы, чтобы код начинался с users.filter
, Общая идея состоит в том, чтобы отфильтровать пользователей, которые имеют права администратора для выбранной службы. Поэтому я попытался извлечь эту логику в одну функцию (userHasAdminRightsForService
), которую я реализовал как функцию, которая возвращает функцию, которую мы хотим использовать для фильтрации пользователей. Благодаря такому дизайну мы получаем код, который выглядит больше как обычный английский: users.filter(userHasAdminRightsForService(selectedService))
вместо users.filter(user => userHasAdminRightsForService(user, selectedService))
,
Array.prototype.some
используется для проверки наличия в массиве хотя бы одного элемента, соответствующего некоторым критериям Так что строка как userService.rights.some(right => lowCase(right.name) === 'admin')
означает, что мы проверяем, если хотя бы одно из прав в userService.rights
удовлетворять критериям, которые должны иметь имя "админ".
// 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>)
);
};
Ваш код действителен, но, как указывает правило, изменение или переназначение параметров функции может привести к непреднамеренному поведению.
Как правило, если вы не хотите полностью отключить правило в .eslintrc
файл, но только для того, чтобы подавить конкретное возникновение ошибки eslint, используйте один из комментариев, запрещающих правила, это также несколько указывает на то, что вы знаете, что делаете.
Может быть, вы могли бы переписать без отключения правила?
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>
);
});
};
Мы решили это так, намного чище и меньше кода (убрано 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>
));