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

如何在React中递归渲染嵌套层级的列表组件?

Implementing Nested Lists with React & React-Redux (Using Lft/Rgt Nested Set Model)

Hey there! I get that moving from native DOM recursion to React's declarative style can feel a bit tricky at first, but it's actually a perfect fit once you wrap your head around it. Let's walk through the steps to build your nested list structure, using your existing Redux setup and the Lft/Rgt props from your items.

Step 1: Convert Flat Data to a Tree Structure

First, since your server returns a flat array of items with Lft and Rgt values (the nested set model), we need to convert this into a hierarchical tree. This makes it way easier for React to render recursively.

Here's a helper function to do that:

// Takes a flat array of items with Lft/Rgt and returns a nested tree
const buildNestedTree = (flatItems) => {
  const tree = [];
  const itemMap = {};

  // First, create a map of items by ID (or whatever unique identifier you use)
  flatItems.forEach(item => {
    itemMap[item.id] = { ...item, children: [] };
  });

  // Then, iterate through each item to assign children
  flatItems.forEach(item => {
    const currentItem = itemMap[item.id];
    // Find parent: item where parent.Lft < current.Lft and parent.Rgt > current.Rgt
    const parent = flatItems.find(
      potentialParent => 
        potentialParent.Lft < currentItem.Lft && 
        potentialParent.Rgt > currentItem.Rgt &&
        // Ensure it's the direct parent (no intermediate items)
        !flatItems.some(
          intermediate => 
            intermediate.Lft > potentialParent.Lft && 
            intermediate.Lft < currentItem.Lft && 
            intermediate.Rgt > currentItem.Rgt && 
            intermediate.Rgt < potentialParent.Rgt
        )
    );

    if (parent) {
      itemMap[parent.id].children.push(currentItem);
    } else {
      // No parent means it's a top-level item
      tree.push(currentItem);
    }
  });

  return tree;
};

Step 2: Build the Recursive Item Component

React components can call themselves recursively—this is the magic that makes nested lists straightforward. We'll create an Item component that renders its own content, and if it has children, renders a nested <ul> with more Item components.

import React from 'react';
import { memo } from 'react';

// Use React.memo to optimize re-renders (optional but recommended for large lists)
const Item = memo(({ item }) => {
  return (
    <li>
      {/* Render your item content here (e.g., item.name, item.description) */}
      {item.name}
      {/* If there are children, render the nested list */}
      {item.children.length > 0 && (
        <ul>
          {item.children.map(childItem => (
            <Item key={childItem.id} item={childItem} />
          ))}
        </ul>
      )}
    </li>
  );
});

export default Item;

Step 3: Integrate with React-Redux in Your ItemsList Component

Now, update your ItemsList component to fetch the flat items from Redux, convert them to a tree, and render the top-level items.

import React from 'react';
import { useSelector } from 'react-redux';
import Item from './Item';
import { buildNestedTree } from './utils';

const ItemsList = () => {
  // Fetch the flat items from your Redux store
  const flatItems = useSelector(state => state.items.itemsList);
  // Convert to nested tree (use useMemo to avoid re-computing on every render)
  const nestedTree = React.useMemo(() => buildNestedTree(flatItems), [flatItems]);

  return (
    <div>
      <ul>
        {nestedTree.map(topLevelItem => (
          <Item key={topLevelItem.id} item={topLevelItem} />
        ))}
      </ul>
    </div>
  );
};

export default ItemsList;

Key Tips & Optimization Notes

  • Memoization: Wrapping Item with React.memo and using useMemo for the nested tree helps prevent unnecessary re-renders, which is crucial for large or frequently updating lists.
  • Unique Keys: Always use a unique, stable key (like the item's ID) when mapping components—this helps React track changes efficiently without re-rendering the entire list.
  • Error Handling: Add checks for missing Lft/Rgt values or invalid data to avoid runtime errors, especially since the data comes from an external server.
  • Alternative Data Handling: If your server can return the nested tree directly (instead of flat Lft/Rgt data), that would save you the conversion step—but if you can't change the server response, the helper function above works perfectly.

That's it! This approach mirrors the recursive logic you used with native DOM, but in React's declarative style—so you let React handle the DOM updates instead of manipulating elements directly.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:17:39