This is not something new but for me doing toggle among the side menu item is bit challenging in React application. Please have a look in code and suggest the possible solution:
Here I have multiple menu item and if I click on perticular menu item it should show selected/active:
<div className="offcanvas offcanvas-start sidebar-nav theme-custom-gray"
tabindex="-1"
id="sidebar">
<ul>
<li>
<i>
Dashboard
</li>
<li><hr /></li>
<li>
product
</li>
<li>
<a href="#layouts">
<i>
Create New
<i>
</a>
<ul>
<li>
MenuItem
</li>
<li>
product 1
</li>
<li>
product 2
</li>
<li>
product 3
</li>
</ul>
</li>
<li>
<i>
View List
</li>
<li><hr /></li>
</ul>
App.jsx:
import { useState } from "react";
import "./styles.css";
const menuItems = ["MenuItem 1", "MenuItem 2", "MenuItem 3", "MenuItem 4"];
const App = () => {
const [selectedMI, setSelectedMI] = useState(menuItems[0]);
return (
<ul>
{menuItems.map((menuItem) => (
<li
className={selectedMI === menuItem ? "selected" : ""}
onClick={() => setSelectedMI(menuItem)}
>
{menuItem}
</li>
))}
</ul>
);
};
export default App;
styles.css:
li {
cursor: pointer;
}
li.selected {
text-decoration: underline;
}
Related
const BreadCrumbs = (props) => {
const [visible, setVisible] = React.useState(false);
return (
<BreadcrumbsDiv>
<li>
<a>Home</a>
</li>
<li>
<a>Grandparent A</a>
</li>
<li>
<a onClick={() => setVisible(!visible)}> . . . </a>
{visible && (
<SubBreadcrumb>
<li>
<a>Parent B</a>
</li>
<li>
<a>Child C</a>
</li>
<li>
<a>Child D</a>
</li>
<li>
<a>Child E</a>
</li>
<li>
<a>Child F</a>
</li>
</SubBreadcrumb>
)}
</li>
<li>
<a>Parent B</a>
</li>
<li>
<a>Child C</a>
</li>
<li>
<a>Child D</a>
</li>
<li>
<a>Child E</a>
</li>
<li>
<a>Child F</a>
</li>
</BreadcrumbsDiv>
);
};
Now it is simply the three dot and hide and show and wanted to create after 5th breadcrumb menu then three dot initiate and 2nd 3rd and 4th will be in on click dot menu breadcrumb
enter image description here
i have an issue. I want the styling of my Link to change based on a state. But the issue is that, i have to click on the link twice before the styling is updated. But when i use the e.prevetndefault, the styling is applied when i click the link but I cannot go to the page. Here is the code.
function Footer(){
const [activeValue, setIsActive] = useState("0")
return(
<div className="footer">
<ul className="socials">
<li> <i className="fab fa-facebook-f"></i> </li>
<li> <i className="fab fa-instagram"></i> </li>
<li> <i className="fab fa-twitter"></i> </li>
<li> <i className="fas fa-podcast"></i> </li>
<li></li>
<li><Link to="/peepNews" onClick={()=>{setIsActive("1")}} style={activeValue=="1"?{color:"#0B77BE",fontWeight:"600"}:null} >Peep News</Link></li>
<li><Link to="/faq" onClick={()=>{setIsActive("2")}} style={activeValue=="2"?{color:"#0B77BE",fontWeight:"600"}:null} >FAQ</Link></li>
<li><a href="" style={{color:"gray", fontWeight:"200"}}>Careers</a></li>
<li><Link to="/legal" onClick={()=>{setIsActive("3")}} style={activeValue=="3"?{color:"#0B77BE",fontWeight:"600"}:null} >Legal</Link></li>
<li>Jupe Global </li>
</ul>
</div>
);
}
EDIT:
This is when i added the useEffect hook. But the issue is that whenever the page re-render, the activeValue is set back to the default Value(0) instead of 1,2,3 etc.
function Footer(){
const [activeValue, setIsActive] = useState("0")
useEffect(() => {
setIsActive(activeValue) ;
alert(activeValue);
},[activeValue])
return(
<div className="footer">
<ul className="socials">
<li> <i className="fab fa-facebook-f"></i> </li>
<li> <i className="fab fa-instagram"></i> </li>
<li> <i className="fab fa-twitter"></i> </li>
<li> <i className="fas fa-podcast"></i> </li>
<li></li>
<li><Link to="/peepNews" onClick={()=>{setIsActive("1")}} style={activeValue=="1"?{color:"#0B77BE",fontWeight:"600"}:null} >Peep News</Link></li>
<li><Link to="/faq" onClick={()=>{setIsActive("2")}} style={activeValue=="2"?{color:"#0B77BE",fontWeight:"600"}:null} >FAQ</Link></li>
<li><a href="" style={{color:"gray", fontWeight:"200"}}>Careers</a></li>
<li><Link to="/legal" onClick={()=>{setIsActive("3")}} style={activeValue=="3"?{color:"#0B77BE",fontWeight:"600"}:null} >Legal</Link></li>
<li>Jupe Global </li>
</ul>
</div>
);
}
With react-router you don't need to use the Link element to navigate to a new page, particularly if you want to functionality to be a little more complex.
You can create a history file and export a history object:
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
Then import history into any file where you would like to navigate using javascript. Then in your file you can simply create a which you can style as you please (or continue to use with e.preventDefault()) which then navigates on the click action.
<li>
<div
onClick={() => {
setIsActive("1");
history.push("/peepNews");
}}
style={activeValue == "1" ? { color: "#0B77BE", fontWeight: "600" } : undefined} >
Peep News</div>
</li>
I'm trying to put a dropdown menu in my navbar. I'm using the materialize framework, and so far this is the only materialize javascript element I can't get to work. Here's the code I am using for the navbar:
import React, { Component } from "react";
import M, { Dropdown } from "materialize-css";
class Navbar extends Component {
componentDidMount() {
M.Dropdown.init(this.Dropdown);
}
render() {
return (
<div className="navbar-fixed">
<nav>
<div class="nav-wrapper purple">
<a href="/" class="brand-logo">
Logo
</a>
<a class="dropdown-trigger btn right" data-target="dropdown1">
Drop Me!
</a>
<ul
id="dropdown1"
class="dropdown-content"
ref={Dropdown => {
this.Dropdown = Dropdown;
}}
>
<li>
one
</li>
<li>
two
</li>
<li class="divider" tabindex="-1" />
<li>
three
</li>
<li>
<a href="#!">
<i class="material-icons">view_module</i>four
</a>
</li>
<li>
<a href="#!">
<i class="material-icons">cloud</i>five
</a>
</li>
</ul>
</div>
</nav>
</div>
);
}
}
export default Navbar;
Essentially I click the element and nothing happens. Not sure what I'm doing wrong, and I can't find anything similar on Stack overflow. Here's the code sandbox... https://codesandbox.io/s/dawn-snow-3cmdv
Thanks!
I'm trying to redo my menu with React Hooks and here's my latest attempt.
The only issue I have is that when I click sub-menu-click, all the sub menu opens.
How can I make it so that only the child is open when the parent (i.e. Item 1) is clicked?
Thank you.
import React, { useState } from 'react';
export default () => {
const [menuOpen, setMenuOpen] = useState(false);
const [subMenuOpen, setSubMenuOpen] = useState(false);
const toggleClassName = menuOpen ? 'is-open' : '';
const data = useStaticQuery(graphql`
query {
site {
siteMetadata {
title
}
}
}
`);
return (
<Layout>
<Menu>
<div class="menu-left">
<Link to="/">{data.site.siteMetadata.title}</Link>
</div>
<Hamburger
className={toggleClassName}
onClick={() => setMenuOpen(!menuOpen)}
>
<span></span>
<span></span>
<span></span>
</Hamburger>
<div class="menu-right">
<ul className={toggleClassName}>
<li class="menu-item has-children">
<Link to="/">
Item 1
</Link>
<div
class={`sub-menu-click`}
onClick={() => setSubMenuOpen(!subMenuOpen)}
>
<span></span>
</div>
<ul
class={`sub-menu && ${
subMenuOpen ? 'is-open' : ''
}`}
>
<li class="menu-item">Sub-Item 1</li>
<li class="menu-item">Sub-Item 2</li>
<li class="menu-item">Sub-Item 3</li>
</ul>
</li>
<li class="menu-item has-children">
<Link to="/">
Item 2
</Link>
<div
class={`sub-menu-click`}
onClick={() => setSubMenuOpen(!subMenuOpen)}
>
<span
class={`${subMenuOpen ? 'is-open' : ''}`}
></span>
</div>
<ul
class={`sub-menu && ${
subMenuOpen ? 'is-open' : ''
}`}
>
<li class="menu-item">Sub-Item 1</li>
<li class="menu-item">Sub-Item 2</li>
<li class="menu-item">Sub-Item 3</li>
</ul>
</li>
</ul>
</div>
</Menu>
</Layout>
);
};
The simplest solution to this to move the SubMenu to a different component and let it have it's own state.
const SubMenu = () => {
const [subMenuOpen, setSubMenuOpen] = useState(false);
return (
<li class="menu-item has-children">
<Link to="/">
Item 1
</Link>
<div
class={`sub-menu-click`}
onClick={() => setSubMenuOpen(!subMenuOpen)}
>
<span></span>
</div>
<ul
class={`sub-menu && ${
subMenuOpen ? 'is-open' : ''
}`}
>
<li class="menu-item">Sub-Item 1</li>
<li class="menu-item">Sub-Item 2</li>
<li class="menu-item">Sub-Item 3</li>
</ul>
</li>
)
}
and render this component in place for SubMenu in Menu component.
In case you need to control the opening of SubMenu from the Menu component, you have an array of subMenuIds currently open or a single ID according to your use case.
I created a simple dropdown button using react, it's working fine but now I want to use the same logic to use it on Two more buttons.
How can I take the same logic that I'm using in 1st Dropdown menu and use in the other two elements 2nd Dropdown menu and 3rd Dropdown menu ?
Here is a link that shows the code in action : http://codepen.io/rkhayat/pen/e3581b3625fc6b6f8fa5a8dab2a28a41
Here's my code:
class Header extends Component {
constructor(props){
super(props)
this.state = {
open:false
}
}
_handleDropDown(){
this.setState({
open: !this.state.open
})
}
render() {
return (
<nav className="navbar">
<ul>
<li>
<div onClick={this._handleDropDown.bind(this)} className="dropdown open">
<button className="btn btn-link dropdown-toggle "type="button" > 1st Dropdown menu</button>
{
this.state.open
?
<ul className="dropdown-menu">
<li>Adventure Tours</li>
<li><a href="#">Airport transfers</a</li>
<li>Car rental</li>
<li><a href="#">Sightseeing tours</a</li>
</ul>
:
null
}
</div>
</li>
<li>2nd Dropdown menu</li>
<li>3rd Dropdown menu</li>
</ul>
</nav>
)
}
}
Update:
I came up with a solution that work but I don't know if it's a best practice:
Here is the code:
class Header extends Component {
constructor(props){
super(props)
this.state = {
open:false,
open2:false
}
}
_handle1stDropDown(){
this.setState({
open: !this.state.open
})
}
_handle2ndDropDown(){
this.setState({
open2: !this.state.open2
})
}
render() {
return (
<nav className="navbar">
<ul>
<li>
<div onClick={this._handle1stDropDown.bind(this)} className="dropdown open">
<button className="btn btn-link dropdown-toggle "type="button" > 1st Dropdown menu</button>
{
this.state.open
?
<ul className="dropdown-menu">
<li>1st dropdown 1st li</li>
<li><a href="#">1st dropdown 2nd li</a</li>
<li>1st dropdown 3rd</li>
<li><a href="#">1st dropdown 4th</a</li>
</ul>
:
null
}
</div>
</li>
<li>
<div onClick={this._handle2ndDropDown.bind(this)} className="dropdown open">
<button className="btn btn-link dropdown-toggle "type="button" > 2nd Dropdown menu</button>
{
this.state.open
?
<ul className="dropdown-menu">
<li>2nd dropdown 1st li</li>
<li><a href="#">2nd dropdown 2nd li</a</li>
<li>2nd dropdown 3rd li</li>
<li><a href="#">2nd dropdown 4th li</a</li>
</ul>
:
null
}
</div>
</li>
</ul>
</nav>
)
}
}
What you would need to do is extract the button and the dropdown into its own component. In order for that to work you would need to make them compossible components meaning that you would pass in the items in the dropdown as props. I made a codepen showing what I mean
http://codepen.io/finalfreq/pen/ozBxrZ
class Dropdown extends React.Component {
constructor(props) {
super()
}
createItems() {
return this.props.items.map(function(item, index) {
return <li> {item.title} </li>
})
}
render() {
var items = this.createItems();
return (
<div onClick={this.props.onClick} className="dropdown open">
<button className="btn btn-default dropdown-toggle" type="button">
Dropdown
<span className="caret" />
</button>
{
this.props.open
?
<ul className="dropdown-menu">
{items}
</ul>
:
null
}
</div>
)
}
}
you'd have to customize it to your needs but you can put dropdown anywhere just need to give it the right props