You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React.js+TypeScript+Material UI动态生成权限开关:遍历对象数组实现独立功能UI Switch

Dynamic Permission Switches in React + TypeScript + Material UI

Got it, let's refactor your component to handle dynamic permissions instead of relying on hardcoded checkedA/checkedB states. This way, no matter how many permissions get passed in, each will have its own independent switch.

Here's the step-by-step fix:

1. Initialize State from Props

Instead of hardcoding state keys, we'll build our initial state object using the permission_name from each permission in your data_permissions prop. We'll also add a useEffect to update state if the permission list changes later.

2. Update the Change Handler

Use React's functional setState to safely update state based on the latest values—this avoids issues with stale state references.

3. Render One Switch Per Permission

Remove the duplicate hardcoded Switches, and render a single Switch that links directly to the current permission's permission_name (for both the name prop and the checked state lookup).

Full Refactored Code

import React, { useState, useEffect } from 'react';
import { Container, Card, TableContainer, Paper, Table, TableHead, TableRow, TableCell, TableBody, FormGroup, FormControlLabel, Switch } from '@mui/material';
import { useStyles } from './your-styles-file'; // Adjust import as needed

// Define your props type clearly
interface Permission {
  name: string;
  description: string;
  permission_name: string;
}

interface PermissionListProps {
  data_permissions: Permission[];
}

export const PermissionList: React.FC<PermissionListProps> = ({ data_permissions }) => { 
  const classes = useStyles(); 
  // Initialize state with dynamic permission keys, defaulting to false
  const [permissionStates, setPermissionStates] = useState<Record<string, boolean>>({});

  // Update state when the permission list changes
  useEffect(() => {
    const initialStates = data_permissions.reduce((acc, permission) => {
      acc[permission.permission_name] = false; // Set initial checked state here (could also pass initial values if needed)
      return acc;
    }, {} as Record<string, boolean>);
    setPermissionStates(initialStates);
  }, [data_permissions]);

  const handleSwitchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { name, checked } = e.target;
    // Use functional update to get latest state
    setPermissionStates(prevState => ({
      ...prevState,
      [name]: checked
    }));
  }; 

  return ( 
    <Container> 
      <Card> 
        <TableContainer className={classes.scroll} component={Paper}> 
          <Table aria-label="permission table"> 
            <TableHead> 
              <TableRow> 
                <TableCell className={classes.name} align="left">Permission Name</TableCell> 
                <TableCell className={classes.description} align="left">Permission Description</TableCell> 
                <TableCell align="left">Switch</TableCell> 
              </TableRow> 
            </TableHead> 
            <TableBody> 
              {data_permissions.map(permission => ( 
                <TableRow key={permission.permission_name}> {/* Use permission_name as unique key */}
                  <TableCell className={classes.name}>{permission.name}</TableCell> 
                  <TableCell className={classes.description}>{permission.description}</TableCell> 
                  <TableCell> 
                    <FormGroup row className={classes.Permission}> 
                      <FormControlLabel 
                        control={
                          <Switch 
                            checked={permissionStates[permission.permission_name] ?? false} // Fallback to false if state hasn't loaded yet
                            onChange={handleSwitchChange} 
                            name={permission.permission_name} // Link switch to the permission's unique identifier
                          />
                        } 
                        label="Off/On" 
                      /> 
                    </FormGroup> 
                  </TableCell> 
                </TableRow> 
              ))} 
            </TableBody> 
          </Table> 
        </TableContainer> 
      </Card> 
    </Container> 
  ) 
};

Key Notes:

  • We use Record<string, boolean> for the state type to enforce that keys are strings (permission names) and values are booleans.
  • The useEffect ensures that if the data_permissions prop updates (e.g., new permissions are added), our state will sync up automatically.
  • We use permission.permission_name as the key for each TableRow—this is better than name because it's a unique identifier (permission names might collide, but permission_name should be unique).
  • The ?? false in the Switch's checked prop is a safety fallback in case the state hasn't finished initializing yet.

内容的提问来源于stack exchange,提问作者Seb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 16:47:34