I’m using a context to generate tab like elements:
import { createContext } from "react"
let TABS = createContext({
tabs:[],
setTabs:(tab)=>{
const allTabs = this.tabs;
this.tabs = [...allTabs,tab];
}
});
export default TABS;
And I’m using the sidebar menu items to add to the tabs. Also I’m using a state to change sidebar menu’s content:
const DUMMY_DATA = {
"paymentAndRecieve": {
actions: [
{
id: 1,
title: <IntlMessages id="sidebar.paymentAndRecieve.actions.recieve" />,
url: "/paymentAndRecieve/actions/recieve",
},
{
id: 2,
title: <IntlMessages id="sidebar.paymentAndRecieve.actions.pay" />,
url: "/paymentAndRecieve/actions/pay",
},
],
lists: [
{
id: 4,
title: <IntlMessages id="sidebar.paymentAndRecieve.actions.recieve" />,
url: "/paymentAndRecieve/lists/recieve",
},
{
id: 3,
title: <IntlMessages id="sidebar.paymentAndRecieve.actions.pay" />,
url: "/paymentAndRecieve/lists/pay",
},
],
},
"accounting": {
actions: [
{
id: 1,
title: <IntlMessages id="sidebar.accounting.actions.recieve" />,
url: "/paymentAndRecieve/actions/recieve",
},
{
id: 2,
title: <IntlMessages id="sidebar.accounting.actions.pay" />,
url: "/paymentAndRecieve/actions/pay",
},
],
lists: [
{
id: 4,
title: <IntlMessages id="sidebar.accounting.actions.recieve" />,
url: "/paymentAndRecieve/lists/recieve",
},
{
id: 3,
title: <IntlMessages id="sidebar.accounting.actions.pay" />,
url: "/paymentAndRecieve/lists/pay",
},
],
},
};
const Panel = Collapse.Panel;
const SubMenu = Menu.SubMenu;
const MenuItemGroup = Menu.ItemGroup;
const SidebarContent = ({ sidebarCollapsed, setSidebarCollapsed }) => {
const { navStyle, themeType } = useSelector(({ settings }) => settings);
const pathname = useSelector(({ common }) => common.pathname);
const { tabs, setTabs } = useContext(TABS);
const [category, setCategory] = useState([]);
const history = useHistory();
function addTab({ title, id, url }) {
let tabLength = tabs.find((tab) => tab.id === id);
if (!tabLength) {
setTabs([...tabs ,{title: title, id: id, url: url }]);
}
console.log(tabs)
history.push(url);
}
function changeCategory(id) {
const actions = (
<MenuItemGroup key="actions" className="gx-menu-group">
<Collapse accordion>
<Panel showArrow={false} header="عملیات">
{DUMMY_DATA[id].actions.map((option) => {
return (
<Menu.Item key={option.id}>
<button
className={classes.link_option}
onClick={() => {
addTab(option);
}}
>
{option.title}
</button>
</Menu.Item>
);
})}
</Panel>
</Collapse>
</MenuItemGroup>
);
const lists = (
<MenuItemGroup key="lists" className="gx-menu-group">
<Collapse accordion>
<Panel showArrow={false} header="فهرست ها">
{DUMMY_DATA[id].lists.map((option) => {
return (
<Menu.Item key={option.id}>
<button
className={classes.link_option}
onClick={() => {
addTab(option);
}}
>
{option.title}
</button>
</Menu.Item>
);
})}
</Panel>
</Collapse>
</MenuItemGroup>
);
setCategory([actions, lists]);
}
const getNoHeaderClass = (navStyle) => {
if (
navStyle === NAV_STYLE_NO_HEADER_MINI_SIDEBAR ||
navStyle === NAV_STYLE_NO_HEADER_EXPANDED_SIDEBAR
) {
return "gx-no-header-notifications";
}
return "";
};
const selectedKeys = pathname.substr(1);
const defaultOpenKeys = selectedKeys.split("/")[1];
console.log(category);
return (
<>
<SidebarLogo
sidebarCollapsed={sidebarCollapsed}
setSidebarCollapsed={setSidebarCollapsed}
/>
<div className="gx-sidebar-content">
<div
className={`gx-sidebar-notifications ${getNoHeaderClass(navStyle)}`}
>
<UserProfile />
<AppsNavigation />
</div>
<CustomScrollbars
className={`gx-layout-sider-scrollbar ${classes.scrollbar}`}
>
<Menu
defaultOpenKeys={[defaultOpenKeys]}
selectedKeys={[selectedKeys]}
theme={themeType === THEME_TYPE_LITE ? "lite" : "dark"}
mode="inline"
>
{category}
</Menu>
</CustomScrollbars>
<div className={classes.categories}>
<button
className={classes.category}
onClick={() => {
changeCategory("accounting");
}}
>
accounting
</button>
<button
className={classes.category}
onClick={() => {
changeCategory("paymentAndRecieve");
}}
>
Payment & Receive
</button>
</div>
</div>
</>
);
};
export default React.memo(SidebarContent);
and this is how I show my tabs:
const OpentTabs = () => {
const history= useHistory();
const {tabs,setTabs} = useContext(TABS);
function removeTab(id){
const currentTab = tabs.find(tab=> tab.id===id);
setTabs(tabs.filter(tab => tab.id!== id));
if(currentTab.url===window.location.pathname){
console.log(window.location.pathname === tabs[tabs.length-1].url? tabs[tabs.length-2].url:tabs[tabs.length-1].url);
if(tabs.length>1){
history.push(window.location.pathname === tabs[tabs.length-1].url? tabs[tabs.length-2].url:tabs[tabs.length-1].url);
}else{
history.push('/home')
}
}
}
const tabList = tabs.map((tab) => {
return (
<li
key={tab.id}
className={classes.tab}
>
<i className="icon icon-close" onClick={()=>{removeTab(tab.id)}}></i>
<NavLink id={tab.id} to={tab.url} className={isActive =>
isActive
? classes.active
: classes.inactive}>
{tab.title}
</NavLink>
</li>
);
});
return <ul className={classes.ul}>{tabList}</ul>;
};
export default OpentTabs;
But my problem is that when I open a new tab the context value is emptied and the filled therefor it doesn’t keep the previously opened tabs, That’s until a new category is chosen, then it will keep the previous tabs and open a new one But even then it will only change the last tab. what should I do?
have tried using another state and pouring that state into the context but it just made the webpage to breakdown.