解决更多的钩子问题:简易指南
P粉883278265
P粉883278265 2023-08-14 13:19:01
[React讨论组]

我在我的项目中遇到了一些钩子问题。这是一个用于检查用户权限并返回true或false的函数。

import { useSelector } from "react-redux";

const CheckPermission = (module_key, permission_key) => {
  const { user } = useSelector((state) => ({
    user: state.auth.user,
  }));

  const rolePermissions = user?.role?.role_permissions ?? [];

  const return_value = !!rolePermissions.find(
    (p_list) =>
      p_list.module?.key === module_key &&
      p_list.permission?.key === permission_key
  );

  return return_value;
};

export default CheckPermission;

然后我在我的侧边栏组件中使用它

const renderMenu = (menu, key) => {
  if (!CheckPermission(menu.moduleKey, menu.permissionKey)) {
    return null;
  }

  return (
    <Tooltip title={menu.name} placement="right" key={key}>
      <NavLink
        activeClassName={styles.active}
        exact
        className={styles.item}
        to={menu.path}
      >
        <span className={styles.iconBox}>{menu.icon}</span>
        <span className={styles.itemText}> {menu.name}</span>
      </NavLink>
    </Tooltip>
  );
};

export default ({ collapse, onCollapse, isAdmin }) => {
  const { user } = useSelector((state) => ({
    user: state.auth.user,
  }));

  return (
    <Layout.Sider
      theme="light"
      className={classnames(styles.sider, collapse ? styles.collapsed : "")}
      collapsible
      collapsed={collapse}
      onCollapse={onCollapse}
      width={collapse ? 64 : 264}
      onBreakpoint={() => {}}
      breakpoint="xl"
      style={{
        overflow: "auto",
        height: "100vh",
        position: "fixed",
        left: 0,
        top: 0,
        paddingTop: "50px",
      }}
    >
      <div className={styles.action}>
        {user && user.read_only
          ? menus.map((menu, i) => {
              if (menu.name === "Харилцагч") {
                return renderMenu(menu, i);
              } else {
                return (
                  menu &&
                  menu.children &&
                  // eslint-disable-next-line array-callback-return
                  menu.children.map((submenu, j) => {
                    if (submenu.name === "QR данс") {
                      return (
                        <div key={i} className={styles.parentnav}>
                          {renderMenu(submenu, j)}
                        </div>
                      );
                    }
                  })
                );
              }
            })
          : menus.map((menu, i) => {
              if (menu.path) {
                return renderMenu(menu, i);
              } else {
                return (
                  <div key={i} className={styles.parentnav}>
                    {menu.name ? (
                      <div
                        className={`${styles.navlabel}  ${styles.partentText}`}
                      >
                        {menu.name}
                      </div>
                    ) : null}
                    {menu.children.map((submenu, j) => {
                      if (!submenu.path) return null;

                      if (isAdmin) {
                        return renderMenu(submenu, j);
                      } else {
                        return null;
                      }
                    })}
                  </div>
                );
              }
            })}
      </div>
    </Layout.Sider>
  );
};

但是它抛出了"Error: Rendered more hooks than during the previous render.",我该如何在其他地方正确使用我的checkPermission函数。

我尝试在循环中使用checkPermission函数,结果是一样的。

P粉883278265
P粉883278265

全部回复(1)
P粉824889650

"错误:渲染时使用的hooks数量多于上一次渲染时的数量",通常发生在您使用React hooks(例如useSelector)的方式违反了hooks规则时。规则规定,hooks必须始终在函数组件的顶层调用,而不是在循环、条件或嵌套函数中调用。在您的代码中,您似乎在循环和条件中使用了CheckPermission函数。

// Sidebar.js
import React from "react";
import { useSelector } from "react-redux";
import { NavLink, Tooltip } from "your-react-ui-library"; // 导入您的UI库
const Sidebar = ({ collapse, onCollapse, isAdmin, menus }) => {
  const { user } = useSelector((state) => ({
    user: state.auth.user,
  }));

  // 将权限检查逻辑直接移入Sidebar组件
  const checkPermission = (module_key, permission_key) => {
    const rolePermissions = user?.role?.role_permissions ?? [];
    return !!rolePermissions.find(
      (p_list) =>
        p_list.module?.key === module_key &&
        p_list.permission?.key === permission_key
    );
  };

  const renderMenu = (menu, key) => {
    // 使用本地的checkPermission函数进行权限检查
    if (
      !checkPermission(menu.moduleKey, menu.permissionKey) ||
      (!isAdmin && !menu.path)
    ) {
      return null;
    }

    return (
      <Tooltip title={menu.name} placement="right" key={key}>
        <NavLink
          activeClassName={styles.active}
          exact
          className={styles.item}
          to={menu.path}
        >
          <span className={styles.iconBox}>{menu.icon}</span>
          <span className={styles.itemText}> {menu.name}</span>
        </NavLink>
      </Tooltip>
    );
  };

  return (
    <Layout.Sider
      // ... 其他属性和样式 ...
    >
      <div className={styles.action}>
        {user && user.read_only
          ? menus.map((menu, i) => {
              if (menu.name === "Харилцагч") {
                return renderMenu(menu, i);
              } else {
                return (
                  menu &&
                  menu.children &&
                  // eslint-disable-next-line array-callback-return
                  menu.children.map((submenu, j) => {
                    if (submenu.name === "QR данс") {
                      return (
                        <div key={i} className={styles.parentnav}>
                          {renderMenu(submenu, j)}
                        </div>
                      );
                    }
                  })
                );
              }
            })
          : menus.map((menu, i) => {
              if (menu.path) {
                return renderMenu(menu, i);
              } else {
                return (
                  <div key={i} className={styles.parentnav}>
                    {menu.name ? (
                      <div
                        className={`${styles.navlabel} ${styles.partentText}`}
                      >
                        {menu.name}
                      </div>
                    ) : null}
                    {menu.children.map((submenu, j) => {
                      if (!submenu.path) return null;

                      if (isAdmin) {
                        return renderMenu(submenu, j);
                      } else {
                        return null;
                      }
                    })}
                  </div>
                );
              }
            })}
      </div>
    </Layout.Sider>
  );
};

export default Sidebar;
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号