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

React Hooks全局标签页动态元素创建及数据留存问题

Let's break down each of your problems and fix them step by step with practical code adjustments:

1. Auto-display first tab content on page load

The issue is that your nestedData starts as null, so nothing renders until you click a tab. We can fix this by initializing the active tab data when the component mounts or when your source data updates.

Solution:

Add a useEffect hook to set the initial active tab and its data whenever data1 changes (like after login data loads):

import { useState, useEffect } from 'react';

export default function App() {
  const [active_menu, setactive_menu] = useState(0);
  const [nestedData, setnestedData] = useState(null);
  // Convert data1 to a state variable so changes trigger re-renders
  const [data1, setData1] = useState([
    { id: 1, name: "Maxi", myData: [ { data_name: "div1", data_title: "div1 tittle" }, { data_name: "div1", data_title: "div tittle" } ] },
    { id: 2, name: "Phill", myData: [ { data_name: "div21", data_title: "div21 tittle" } ] }
  ]);

  // Initialize first tab on mount or data update
  useEffect(() => {
    if (data1.length > 0) {
      setactive_menu(0);
      setnestedData(data1[0]);
    }
  }, [data1]);

  // ... rest of your code
}

2. Implement ADD button for new tabs (max 4)

Your data1 was a static variable, so adding tabs wouldn't trigger re-renders. First, we need to make data1 a state variable, then implement the addnewTab function to safely add new tabs with default values.

Solution:

Update your addnewTab function to create a new tab, ensure unique IDs, and cap the total at 4:

const addnewTab = () => {
  if (data1.length >= 4) return; // Prevent more than 4 tabs

  // Generate unique ID and default name
  const newTabId = data1.length > 0 ? Math.max(...data1.map(tab => tab.id)) + 1 : 1;
  const newTab = {
    id: newTabId,
    name: `Tab ${data1.length + 1}`,
    myData: [] // Empty initial content
  };

  // Update state with new tab
  setData1([...data1, newTab]);
  // Auto-switch to the new tab
  setactive_menu(data1.length);
  setnestedData(newTab);
};

3. Persist created elements when switching tabs

The problem is that you're not saving new elements back to the main data1 state—you're only updating nestedData, which is a local copy. We need to update the corresponding tab's myData in the main state.

Solution:

Modify the Create_element function to update the main data1 state and sync nestedData:

const Create_element = () => {
  // Create a new div object with unique default values
  const newDiv = {
    data_name: `div-${Date.now()}`,
    data_title: `New Div Title`
  };

  // Update the active tab's myData in the main data array
  const updatedData = data1.map((tab, index) => {
    if (index === active_menu) {
      return {
        ...tab,
        myData: [...tab.myData, newDiv]
      };
    }
    return tab;
  });

  setData1(updatedData);
  // Sync nestedData to show the new element immediately
  setnestedData({...data1[active_menu], myData: [...data1[active_menu].myData, newDiv]});
};

4. Support tab creation when initial data is empty

If your initial data1 is empty (no login data), we just need to set the initial state to an empty array and ensure the ADD button works as expected.

Solution:

Set initial data1 to an empty array, and the addnewTab function will handle creating up to 4 tabs:

const [data1, setData1] = useState([]); // Empty initial state

When you fetch login data later, just update the state with setData1(fetchedJsonData)—the useEffect we added earlier will automatically set the first tab if data exists.


Full Modified Core Code

import { useState, useEffect } from 'react';
import NEsted from './NEsted'; // Adjust import path as needed
import RightBar from './RightBar'; // Adjust import path as needed

export default function App() {
  const [active_menu, setactive_menu] = useState(0);
  const [nestedData, setnestedData] = useState(null);
  // Initialize with empty array or your login data
  const [data1, setData1] = useState([]);

  // Initialize first tab when data loads/changes
  useEffect(() => {
    if (data1.length > 0) {
      setactive_menu(0);
      setnestedData(data1[0]);
    }
  }, [data1]);

  const Tab_click = (index, li) => {
    setactive_menu(index);
    setnestedData(li);
  };

  const Create_element = () => {
    const newDiv = {
      data_name: `div-${Date.now()}`,
      data_title: `New Div Title`
    };

    const updatedData = data1.map((tab, index) => {
      if (index === active_menu) {
        return {
          ...tab,
          myData: [...tab.myData, newDiv]
        };
      }
      return tab;
    });

    setData1(updatedData);
    setnestedData({...data1[active_menu], myData: [...data1[active_menu].myData, newDiv]});
  };

  const addnewTab = () => {
    if (data1.length >= 4) return;

    const newTabId = data1.length > 0 ? Math.max(...data1.map(tab => tab.id)) + 1 : 1;
    const newTab = {
      id: newTabId,
      name: `Tab ${data1.length + 1}`,
      myData: []
    };

    setData1([...data1, newTab]);
    setactive_menu(data1.length);
    setnestedData(newTab);
  };

  return (
    <div className="App row">
      {data1.map((li, index) => (
        <div className="col-4 col-sm-4 col-md-3 col-lg-3 col-xl-3" key={li.id}> {/* Use tab.id as key instead of index */}
          <div className={ index === active_menu ? "row dashboard_single_cont_active" : "row dashboard_single_cont" }
            onClick={() => Tab_click(index, li)} 
          >
            <div className="dashboard_name col-10 col-sm-10 col-md-9 col-lg-10 col-xl-10">
              {li.name}
            </div>
            <div className={ active_menu === index ? "dashboard_option_active col-2 col-sm-2 col-md-3 col-lg-2 col-xl-2" : "dashboard_option col-2 col-sm-2 col-md-3 col-lg-2 col-xl-2" }
              align="center" 
            ></div>
          </div>
        </div>
      ))}
      {data1.length < 4 && (
        <span onClick={addnewTab} style={{cursor: 'pointer', padding: '0 1rem'}}>ADD</span>
      )}
      <div className="col-11 col-sm-11 col-md-11 col-lg-11 col-xl-11">
        <div className="row">
          {nestedData?.myData.map((li, index) => ( // Optional chaining to avoid errors if nestedData is null
            <div className="col-11 col-sm-11 col-md-8 col-lg-6 col-xl-6" key={index}>
              <NEsted data={li} />
              <br></br>
            </div>
          ))}
        </div>
      </div>
      <RightBar Create_element={Create_element} />
    </div>
  );
}

Quick Notes:

  • Changed the tab key from index to li.id for better React list performance
  • Added optional chaining (nestedData?.myData) to avoid errors when nestedData is null (like initial empty state)
  • Added cursor style to the ADD button for better UX

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 06:22:40