简体   繁体   English

如何修复我的过滤器中的此ESlint(无参数重新分配)错误

[英]How to fix this ESlint (no-param-reassign) error in my Filter

I'm trying to find only users that have a specific service. 我正在尝试仅查找具有特定服务的用户。 Each user has an array of Services. 每个用户都有一系列服务。 And the match I need to find is the following: 我需要找到的匹配项如下:

userService.name === service.name && !user.disabled

Code below works, but has ESlint errors dealing with a param-reassignment. 下面的代码有效,但是在处理参数重新分配时出现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;
  })));
};

Could this be refactored with .find ? 可以使用.find重构.find吗?

I would suggest restructuring the code, because now it relies on mutations inside of a .map call, which could become pretty hard to reason about. 我建议重新组织代码,因为现在它依赖于.map调用中的突变,这可能很难推理。 I cant check that my suggested code actually works, but I think it expresses the intent of what you are trying to do more clearly. 我无法检查我建议的代码是否确实有效,但是我认为它表达了您尝试做的事情的意图。

Edit . 编辑 Explanation: In short, we have a list of users where only some are relevant. 说明:简而言之,我们有一个用户列表,其中只有一些是相关的。 That tells us we probably would want the code to start with users.filter . 这告诉我们,我们可能希望代码以users.filter The general idea is to filter out users that have admin rights for the selected service. 通常的想法是过滤出具有所选服务管理员权限的用户。 So I tried to extract that logic into one function ( userHasAdminRightsForService ), which I implemented as a function that returns the function that we will want to use to filter the users. 因此,我试图将该逻辑提取到一个函数( userHasAdminRightsForService )中,该函数实现为一个函数,该函数返回将要用于过滤用户的函数。 Because of this design, we get code that reads more like regular English: users.filter(userHasAdminRightsForService(selectedService)) instead of users.filter(user => userHasAdminRightsForService(user, selectedService)) . 由于这种设计,我们得到的代码读起来更像普通英语: users.filter(userHasAdminRightsForService(selectedService))而不是users.filter(user => userHasAdminRightsForService(user, selectedService))

Array.prototype.some is used to check if an array has at least one element that meets some criteria. Array.prototype.some用于检查数组是否具有至少一个满足某些条件的元素。 So a line like userService.rights.some(right => lowCase(right.name) === 'admin') means that we check if at least one of the rights in userService.rights satisfy the criteria that it should have the name 'admin'. 因此,像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>)
  );
};

Your code is valid, but as the rule points out , modifying or reassignment of function parameters can lead to unintended behavior. 您的代码是有效的,但是如规则所指出 ,修改或重新分配函数参数可能会导致意外行为。

Generally if you don't want to disable a rule completely in the .eslintrc file but only want to suppress specific occurrence of an eslint error use one of rule-disabling comments , it also somewhat indicates you know what you are doing. 通常,如果您不想完全禁用.eslintrc文件中的规则,而只想使用禁用规则的注释之一来抑制eslint错误的特定发生,则这也说明您知道自己在做什么。

maybe you could rewrite without disabling the rule? 也许您可以在不禁用规则的情况下进行重写?

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>
          );
    });
};

We ended up solving it this way, much cleaner and way less code too (removed 2 functions)! 我们最终以这种方式解决了问题,它更加简洁,代码也更少(删除了2个功能)! Missing part was chaining filters then using .find 缺少的部分是链接过滤器,然后使用.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>
    ));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM