Issues You are Facing
- If length of data is less than four I am providing a plus button to create on more tab (give it default name), but I am not getting any idea how can I create the new one.
Here you want to get a new name, i.e. a form on the page with a text input, random generate name, use a prompt as I did below. Call setData
and use a functional state update to spread existing data into a new array and append a new data object.
const addNewTab = () => {
/**
* window.prompt is just a quick way to request input from user.
*/
const name = window.prompt('Enter Name');
/**
* logic to generate next id, but could be anything really
*/
const id = generateId();
if (name) {
setData((data) => [...data, new Data(id, name)]);
}
};
- When I click on side button to create one dive inside tab, and I go to other tab and come back again I want that created
div
should not gets deleted.
A couple things going on here. First, you defined data1
in the function body so it is reset every render cycle. Keep the data in state, data
can be provided as initial state. Second, you need to add the created elements. Do this by updating state.
Move data1
out of the component and define local component state initialized with data
(update all references in render from data
to data
).
const [data, setData] = useState(data1);
Similar approach as adding a new tab, get the new data name and title. Here we call setData
and again use a functional state update, but this time we'll map the existing state to a new array. When the array index matches the active tab index this is the data object we need to updated. Spread its myData
into a new array and append the new data object. If index isn't a match then just return the element.
const Create_element = () => {
/**
* window.prompt is just a quick way to request input from user.
*/
const data_name = window.prompt('Enter Data Name');
const data_title = window.prompt('Enter Data Title');
if (data_name && data_title) {
setData(data => data.map((el, i) => i === active_menu ? {
...el,
myData: [...el.myData, { data_name, data_title }],
} : el))
}
};
- Suppose I have 3 tabs (data) so when page loads the first tab data I want to show, but it is not showing up I need to click there only it is showing up.
Issue here is caused by keeping a separate nestedData
state object that is only ever updated when a tab is clicked. When a new element is added to the active tab's myData
array nestedData
isn't updated. Solution here is to simply render the nested data directly in the UI.
Update the tab's onClick handler to simply set the active menu (index).
onClick={() => setactive_menu(index)}
Render the myData
directly from the new data
state.
data[active_menu].myData.map((li, index) => (...
- If the data is null then I can create up to 4 tabs this also I a=want some Idea to do it.
Conditionally rendering the ADD button will control this.
{data.length < 4 && <button onClick={addNewTab}>ADD</button>}
Full Code
import React, { useState } from "react";
import "./styles.css";
import RightBar from "./Right_option";
import NEsted from "./Nested";
import "bootstrap/dist/css/bootstrap.min.css";
/**
* https://stackoverflow.com/questions/63814645/how-to-create-dynamic-elements-inside-global-tabs
*/
const data1 = [
{
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"
}
]
}
];
/**
* Data object constructor
* @param {number} id new data object id
* @param {string} name new data object name
* @example
* new Data(1, 'Bill')
*/
const Data = (id, name) => ({ id, name, myData: [] });
/**
* Id generator hook
* @param {number} [seed=0] initial id generator value
* @returns {function}
*/
const useIdGenerator = (seed = 0) => {
function* genId(seed = 0) {
let i = seed;
while (true) yield i++;
}
const generator = genId(seed);
return () => generator.next().value;
};
export default function App() {
const generateId = useIdGenerator(5);
const [data, setData] = useState(data1);
const [active_menu, setactive_menu] = useState(0);
const Create_element = () => {
/**
* window.prompt is just a quick way to request input from user.
*/
const data_name = window.prompt("Enter Data Name");
const data_title = window.prompt("Enter Data Title");
if (data_name && data_title) {
setData((data) =>
data.map((el, i) =>
i === active_menu
? {
...el,
myData: [...el.myData, { data_name, data_title }]
}
: el
)
);
}
};
const addNewTab = () => {
/**
* window.prompt is just a quick way to request input from user.
*/
const name = window.prompt("Enter Name");
if (name) {
setData((data) => [...data, new Data(generateId(), name)]);
}
};
return (
<div className="App row">
{data.map((li, index) => (
<div className="col-4 col-sm-4 col-md-3 col-lg-3 col-xl-3" key={index}>
<div
className={
index === active_menu
? "row dashboard_single_cont_active"
: "row dashboard_single_cont"
}
onClick={() => setactive_menu(index)}
>
<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>
))}
{data.length < 4 && <button onClick={addNewTab}>ADD</button>}
<div className="col-11 col-sm-11 col-md-11 col-lg-11 col-xl-11">
<div className="row">
{data[active_menu].myData.map((li, index) => (
<div
key={index}
className="col-11 col-sm-11 col-md-8 col-lg-6 col-xl-6"
>
<NEsted data={li} />
<br></br>
</div>
))}
</div>
</div>
<RightBar Create_element={Create_element} />
</div>
);
}