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

React.js CRUD最佳实践与组件层级探讨及个人项目结构问询

React CRUD Component Hierarchy: Feedback & Optimization Tips

Hey there! Let’s break down your current component setup and align it with React CRUD best practices—your initial approach has some solid foundations, but there are ways to make it more maintainable and scalable.

First, Your Current Hierarchy: Is It Reasonable?

Short answer: Yes, it’s a reasonable starting point. You’re following the classic "container + presentational component" pattern:

  • The App component (stateful) handles data fetching (your GET request) and holds the source of truth for your item list.
  • ListItem and Item are stateless, purely focused on rendering UI based on props.

This separation of concerns is great—it keeps your presentation components decoupled from data logic, making them easier to test and reuse. That said, we can refine this setup for better scalability.

Optimization Tips to Follow Best Practices

1. Split the Container Logic Out of App

Right now, App is doing two jobs: managing item data/API calls and acting as the root component. As your app grows (adding create/update/delete flows, routing, global UI elements), this will get messy.

Instead, create a dedicated container component like ItemListContainer to handle all CRUD-related logic:

  • Move your GET request (and eventually POST/PUT/DELETE calls) into this component using useEffect.
  • Use useState to manage items, loading, and error states here.
  • Pass the item list and CRUD callbacks (e.g., handleDelete, handleUpdate) down to presentation components.

Your App can then focus on being the root wrapper—handling routing, global navigation, or layout, rather than data logic.

Example snippet for ItemListContainer:

import { useState, useEffect } from 'react';
import ListItem from './ListItem';

const ItemListContainer = () => {
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchItems = async () => {
      try {
        const res = await fetch('/api/items');
        const data = await res.json();
        setItems(data);
      } catch (err) {
        setError('Failed to fetch items');
      } finally {
        setLoading(false);
      }
    };
    fetchItems();
  }, []);

  const handleDelete = async (itemId) => {
    // Call Spring Boot DELETE API, then update items state
    await fetch(`/api/items/${itemId}`, { method: 'DELETE' });
    setItems(items.filter(item => item.id !== itemId));
  };

  if (loading) return <div>Loading items...</div>;
  if (error) return <div className="error">{error}</div>;

  return <ListItem items={items} onDelete={handleDelete} />;
};

export default ItemListContainer;

2. Simplify Unnecessary Component Layers

Your ListItem component is currently a stateless wrapper for rendering multiple Items. Ask yourself: does it add any unique logic (like filtering, sorting, or wrapping items in a styled container)?

  • If it’s just a pass-through component (e.g., only returns <div>{items.map(Item)}</div>), you can remove this layer entirely. Instead, map over items directly in your ItemListContainer and render Item components.
  • If it does handle layout or minor UI logic (like adding a "no items" message), keep it—but make sure its purpose is clear.

3. Empower the Item Component for Interaction

Right now, Item is purely presentational. As you add update/delete functionality, let Item own its interactive elements (like delete/edit buttons) by passing down callbacks from the container:

// Item.jsx
const Item = ({ item, onDelete, onEdit }) => {
  return (
    <div className="item">
      <h3>{item.title}</h3>
      <p>{item.description}</p>
      <button onClick={() => onEdit(item.id)}>Edit</button>
      <button onClick={() => onDelete(item.id)}>Delete</button>
    </div>
  );
};

This keeps Item self-contained—its UI and related interactions live in one place, making it easier to modify later.

4. Add Loading & Error States

Your initial setup likely doesn’t handle loading spinners or error messages. Adding these states in your container component (as shown in the ItemListContainer example) improves UX significantly—users won’t stare at a blank screen while waiting for data, and they’ll know if something goes wrong.

5. Avoid Prop Drilling (For Larger Apps)

If your app grows beyond just a list (e.g., an edit form component that needs to update items), passing props through multiple layers can become tedious (this is called "prop drilling").

For this, consider using:

  • React Context API: Create an ItemContext to share item data and CRUD methods across components without prop drilling.
  • Redux Toolkit: If you need more complex state management (like tracking edit modes, or sharing state across many pages), this is a great option for centralized state.

Final Thoughts

Your initial component hierarchy is a strong starting point, but refining it by separating concerns, simplifying layers, and adding robust state management will make your CRUD implementation much easier to maintain as you add features.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:17:41