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

基础版React用户管理应用的优化方向与建议

React用户管理应用优化建议

你已经实现了用户管理的基础CRUD功能,以下是针对代码和功能的具体优化方向及修改建议:


现有代码整理

App.jsx

import { useState } from 'react'
import './App.css'
import { Users } from './components/Users'
import { createUser, deleteUser, getUsers } from './services/user.service'
import { UserEdit } from './components/UserEdit'

function App() {
  const [users, setUsers] = useState(getUsers())

  const handleNewUser = (user) => {
    createUser(user)
    setUsers(getUsers())
  }

  const handleDeleteUser = (user)=> {
    deleteUser(user)
    setUsers(getUsers())
  }

  return (
    <>
      <h2><i className="bi-person text-primary me-2"></i>User-Administration</h2>
      <div className="card">
        <h4>New User</h4>
        <UserEdit onNewUser={handleNewUser} ></UserEdit>
        <hr />
        <h4>List of Users</h4>
        <Users users={users} onDelete={handleDeleteUser}/>
      </div>
    </>
  )
}

export default App

Users.jsx

/* eslint-disable react/prop-types */
import { User } from "./User"

export const Users = ({users, onDelete}) => {
    return (
        <table className="table">
            <thead>
                <tr>
                    <th>#</th>
                    <th>Username</th>
                    <th>Role</th>
                    <th>Actions</th>
                </tr>
            </thead>

            <tbody className="users">
                {users.map(user => (
                    <User key={user.id} user={user} onDelete={onDelete}/>
                ))}
            </tbody>
        </table>       
    )
}

User.jsx

/* eslint-disable react/prop-types */
export const User = ({user, onDelete}) => {
    return (
        <tr>
                <td>{user.id}</td>
                <td>
                    <span className="me-2">{user.name}</span>
                </td>
                <td>
                    <select className="form-control form-control-sm" name="roles" id="roles" value={user.role} disabled>
                        <option value="1">Admin</option>
                        <option value="2">User</option>
                        <option value="3">Generic</option>
                    </select>
                </td>
                <td>
                    <button className="btn btn-outline-primary me-2" onClick={() => onDelete(user)}><i className="bi-pencil"></i></button>
                    <button className="btn btn-outline-danger" onClick={() => onDelete(user)}><i className="bi-trash"></i></button>
                </td>
        </tr>
    )
}

UserEdit.jsx

/* eslint-disable react/prop-types */
import { useState } from "react"

export const UserEdit = ({onNewUser}) => {
    const [name, setName] = useState('')
    const [role, setRole] = useState('')

    const handleSubmit = (event) => {
        event.preventDefault()

        if(name != '') {
            const user = {name, role}
            onNewUser(user)

            resetInput()
        }
    }

    const resetInput = () => {
        setName('')
        setRole('')
    }

    return (
        <form className="user-form" onSubmit={handleSubmit}>
            <label htmlFor="name">Name</label>
            <input className="form-control" type="text" id="name" value={name} onChange={(event) => setName(event.target.value)} placeholder="Fill in Name" required/>
            
            <label htmlFor="role">Rolle</label>
            <select className="form-select mb-3" name="role" id="role" value={role} onChange={(event) => setRole(event.target.value)} required>
                <option value="">Select Role</option>
                <option value="1">Admin</option>
                <option value="2">User</option>
                <option value="3">Generic</option>
            </select>

            <button className="btn btn-outline-secondary" type="submit">Add</button>
        </form>
    )
}

user.service.js

import { uid } from 'uid';

let users = [
    {
        id: uid(),
        name: 'Max Mustermann',
        role: 1
    }
]

const getUsers = () => {
    return users
}

const createUser = (user) => {
    user.id = uid()  
    users = [user, ...users]
}

const updateUser = (user) => {
    const index = users.findIndex(t => t.id === user.id)
    users[index] = user
    users = [...users]
}

const deleteUser = (user) => {
    const index = users.findIndex(t => t.id === user.id)
    users.splice(index, 1)
    users = [...users]
}


export { getUsers, createUser, updateUser, deleteUser }

具体优化建议

1. 修复核心功能Bug

  • User组件编辑按钮绑定错误:当前编辑按钮触发的是onDelete方法,需修改为触发编辑逻辑:
    // User.jsx
    <button className="btn btn-outline-primary me-2" onClick={() => onEdit(user)}><i className="bi-pencil"></i></button>
    

2. 实现完整编辑功能

  • 复用UserEdit组件支持编辑模式,新增user props区分新增/编辑:
    // UserEdit.jsx
    export const UserEdit = ({ onSubmit, user = null }) => {
      const [name, setName] = useState(user ? user.name : '')
      const [role, setRole] = useState(user ? user.role.toString() : '')
    
      const handleSubmit = (event) => {
        event.preventDefault()
        if (name.trim()) {
          const submitUser = {
            ...user,
            name,
            role: parseInt(role)
          }
          onSubmit(submitUser)
          resetInput()
        }
      }
    
      // 其余代码保持不变
    }
    
  • 在App.jsx中添加编辑状态管理:
    const [editingUser, setEditingUser] = useState(null)
    
    const handleEditUser = (user) => {
      setEditingUser(user)
    }
    
    const handleSubmitUser = (user) => {
      user.id ? updateUser(user) : createUser(user)
      setUsers(getUsers())
      setEditingUser(null)
    }
    
    // 渲染UserEdit时传递参数
    <UserEdit onSubmit={handleSubmitUser} user={editingUser} />
    

3. 数据持久化

  • 将用户数据存储到localStorage,避免刷新丢失:
    // user.service.js
    const STORAGE_KEY = 'user_admin_users'
    
    // 初始化从localStorage读取
    let users = JSON.parse(localStorage.getItem(STORAGE_KEY)) || [
      { id: uid(), name: 'Max Mustermann', role: 1 }
    ]
    
    // 同步到localStorage的工具函数
    const syncToStorage = () => {
      localStorage.setItem(STORAGE_KEY, JSON.stringify(users))
    }
    
    // 修改create/update/delete方法,每次操作后同步
    const createUser = (user) => {
      user.id = uid()
      users = [user, ...users]
      syncToStorage()
    }
    

4. 代码质量与类型安全

  • 启用PropTypes类型检查,替代禁用注释:
    // Users.jsx
    import PropTypes from 'prop-types'
    
    Users.propTypes = {
      users: PropTypes.arrayOf(PropTypes.shape({
        id: PropTypes.string.isRequired,
        name: PropTypes.string.isRequired,
        role: PropTypes.number.isRequired
      })).isRequired,
      onDelete: PropTypes.func.isRequired,
      onEdit: PropTypes.func.isRequired
    }
    
  • (可选)迁移到TypeScript,定义User类型增强代码可读性:
    // types.ts
    export interface User {
      id: string;
      name: string;
      role: 1 | 2 | 3;
    }
    

5. 优化状态更新逻辑

  • 避免依赖service层全局变量,直接通过state更新减少耦合:
    // App.jsx
    const handleDeleteUser = (user) => {
      deleteUser(user)
      setUsers(prev => prev.filter(u => u.id !== user.id))
    }
    

6. 用户体验优化

  • 添加删除确认弹窗,防止误操作:
    // User.jsx
    const handleDelete = () => {
      if (window.confirm(`确定删除用户 ${user.name} 吗?`)) {
        onDelete(user)
      }
    }
    
    <button className="btn btn-outline-danger" onClick={handleDelete}><i className="bi-trash"></i></button>
    
  • 添加空状态提示:
    // Users.jsx
    <tbody className="users">
      {users.length === 0 ? (
        <tr>
          <td colSpan={4} className="text-center py-3">暂无用户,请添加新用户</td>
        </tr>
      ) : (
        users.map(user => (
          <User key={user.id} user={user} onDelete={onDelete} onEdit={onEdit}/>
        ))
      )}
    </tbody>
    

7. 代码结构优化

  • 统一文件名,将service.js改为user.service.js匹配导入路径
  • 提取角色选项常量,避免重复代码:
    // constants.js
    export const ROLE_OPTIONS = [
      { value: '', label: 'Select Role' },
      { value: '1', label: 'Admin' },
      { value: '2', label: 'User' },
      { value: '3', label: 'Generic' }
    ]
    
    在User和UserEdit中复用该常量渲染下拉选项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 17:44:52