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
indextoli.idfor better React list performance - Added optional chaining (
nestedData?.myData) to avoid errors whennestedDatais null (like initial empty state) - Added cursor style to the ADD button for better UX
内容的提问来源于stack exchange,提问作者manish thakur

