I am working on a menu drop down in next.js project,
I made a method to hide and show the data of the sub menu,but I am not able to show the specific sub dropdown. Here is the code
import {useEffect, useState } from "react";
function Header({data}){
const [showMe, setShowMe] = useState(false);
function toggle(param){
console.log(param)
setShowMe(!showMe);
};
return(
<div className="mobile-header">
<div className="mobile-menu">
<div className="menu-icon">
<div className="wrapper">
<input type="checkbox" id="navigation" />
<label for="navigation">
+
</label>
<nav>
<ul>
<li className="menu-heading">
<span>Menu</span>
<span>
<label for="navigation">X</label>
</span>
</li>
{data.menus.map((post, index) => {
return (
<li className="menu-list" id={index}>
{post.title} <span onClick = {(event)=>toggle({index})} index={index} >+</span>
<ul style={{display: showMe?"block":"none"}} index={index} value={index} className="category-one">
{post.menu_columns.map((subItems, sIndex) => {
return <li index={sIndex}>
{subItems.title}
<span>+</span>
<ul className="category-two">
{subItems.menu_items.map((x) => {
return <li>
{x.title}
</li>
})}
</ul>
</li>;
})}
</ul>
</li>)})}
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
)
}
export default Header;
toggle is the function, which responsible to show and hide the data, there is a parameter passed in this function which provide the specific index value, how do we target the specific div by using the index value in this.
Related
There are many similar problems, but I can't solve this background error warning. Strictly speaking, I'm still a novice. I know to change li, but I don't know where to start. Please help me. This error warning:
next-dev.js?3515:20 Warning: validateDOMNesting(...): <li> cannot appear as a descendant of <li>.
at li
at li
at ul
at div
at div
at Top (webpack-internal:///./components/header/Top.js:28:84)
at header
at Header (webpack-internal:///./components/header/index.js:18:11)
at div
at Home
at PersistGate (webpack-internal:///./node_modules/redux-persist/es/integration/react.js:39:5)
at Provider (webpack-internal:///./node_modules/react-redux/es/components/Provider.js:13:3)
at MyApp (webpack-internal:///./pages/_app.js:22:11)
at PathnameContextProviderAdapter (webpack-internal:///./node_modules/next/dist/shared/lib/router/adapters.js:62:11)
at ErrorBoundary (webpack-internal:///./node_modules/next/dist/compiled/#next/react-dev-overlay/dist/client.js:301:63)
at ReactDevOverlay (webpack-internal:///./node_modules/next/dist/compiled/#next/react-dev-overlay/dist/client.js:850:919)
at Container (webpack-internal:///./node_modules/next/dist/client/index.js:62:1)
at AppContainer (webpack-internal:///./node_modules/next/dist/client/index.js:172:11)
at Root (webpack-internal:///./node_modules/next/dist/client/index.js:347:11)
I hope something can help me correct him. Like obsessive-compulsive disorder, I can't face the red color of the back. This is my original code:
import styles from "./styles.module.scss";
import { MdSecurity } from "react-icons/md";
import { BsSuitHeart } from "react-icons/bs";
import { RiAccountPinCircleLine, RiArrowDropDownFill } from "react-icons/ri";
import Link from "next/link";
import { useState } from "react";
import UserMenu from "./UserMenu";
export default function Top() {
const [ loggedIn, setLoggedIn ] = useState(true);
const [visible, setVisible] = useState(false);
return (
<div className={styles.top}>
<div className={styles.top_container}>
<div></div>
<ul className={styles.top_list}>
<li className={styles.li}>
<MdSecurity />
<span>Buyer Prodtection</span>
</li>
<li className={styles.li}>
<span>Customer Service</span>
</li>
<li className={styles.li}>
<span>Help</span>
</li>
<li className={styles.li}>
<BsSuitHeart />
<Link href={"/profile/whishlist"}>
<span>Whishlist</span>
</Link>
</li>
<li
className={styles.li}
onMouseOver={() => setVisible(true)}
onMouseLeave={() => setVisible(false)}
>
{loggedIn ? (
<li className={styles.li}>
<div className={styles.flex}>
<img
src={"/"}
width={22}
height={22}
alt=''
/>
<RiArrowDropDownFill />
</div>
</li>
) : (
<li className={styles.li}>
<div className={styles.flex}>
<RiAccountPinCircleLine />
<span>Account</span>
<RiArrowDropDownFill />
</div>
</li>
)}
{visible && <UserMenu loggedIn={loggedIn} />}
</li>
</ul>
</div>
</div>
);
}
You cannot nest li tags in html.
For example
<ul>
<li>
<li></li>
</li>
</ul>
If you would like a nested list, you can do this
<ul>
<li>
<ul>
<li></li>
</ul>
</li>
</ul>
I'm working on a fictive project for my webdev formation, and I would need just a little help in fixing my filter system for my gallery. It's pretty straightforward, you click on a category and the gallery displays the images corresponding to the category. Everything (finally) works pretty nicely, the only two problems that keep bugging me are:
-Once a category is checked, I can't uncheck it and have to check another category instead (which automatically unchecks the previous one);
-And as the title of my question suggests, I can only select one category at a time.
I would like the user to be able to check multiple categories in order to display all photos corresponding to the categories selected, thus meaning I would like the user to be able to uncheck a category, and if no categories are checked, then the gallery would display all photos of the api.
Thank you for your help and your research.
import Head from 'next/head'
import Image from 'next/image'
import { useRouter } from 'next/router'
import { useState } from 'react'
import Nav from '../components/nav'
import styles from '../styles/style.module.css'
export default function Gallery({ res, res2 }) {
const [targetCategory, setTargetCategory] = useState("");
return(
<main className={`${styles.container} ${styles.gallery}`}>
{/* NAVBAR */}
<div className={`${styles.menu}`}>
<Nav />
</div>
{/* GALLERY FILTER - MOBILE COLLAPSIBLE */}
<div className={`${styles.filter}`}>
<div className="container-fluid">
<nav className="navbar navbar-expand-lg">
<button className="navbar-toggler text-white"
type="button"
data-bs-toggle="collapse"
data-bs-target="#filterContent"
aria-controls="filterContent"
aria-expanded="false"
aria-label="Toggle navigation">
<span className="align-self-center">Filtres</span>
<i className="bi bi-list fs-1"/>
</button>
<div className="collapse navbar-collapse" id="filterContent">
<form id="img-sort" action="">
<ul className="nav navbar-nav">
{res2.data.map((category) => (
<>
<label key={category.id} className={styles.formControl}>
<input
type="checkbox"
name="checkbox"
id={category.attributes.name}
value={category.attributes.name}
checked={targetCategory === category.attributes.name}
onClick={(e) => setTargetCategory(e.target.value)}/>
{category.attributes.name}
</label>
</>
))}
</ul>
</form>
</div>
</nav>
</div>
</div>
{/* GALLERY CONTENT */}
<div className={`${styles.pictures_holder}`}>
<div className={`${styles.pictures}`}>
{res.data.filter((photo) => photo.attributes.category.data.attributes.name.includes(targetCategory)).map((photo) => (
<div key={res.id}>
<img
src={`http://localhost:1337` + photo.attributes.img.data[0].attributes.formats.small.url}
alt={photo.attributes.img.data[0].attributes.formats.small.name}
/>
<p className="text-white text-center">{photo.attributes.name}</p>
</div>
))}
</div>
</div>
</main>
)
}
export async function getStaticProps() {
try {
const res = await fetch("http://localhost:1337/api/photos?populate=*").then((res) => res.json());
const res2 = await fetch("http://localhost:1337/api/categories?populate=*").then((res2) => res2.json());
return {
props: { res, res2 }
};
} catch (err) {
console.error(err);
}
}
When I click the button to toggle the mobile nav bar it's not working. I am using Bulma css framework with react. Here is the React nav bar component:
onst Header = (props) => {
const dispatch = useDispatch()
const { loginUser, isAuthenticated, history, errors } = props;
const dropdownRef = useRef(null);
const [isActive, setIsActive] = useDetectOutsideClick(dropdownRef, false);
const [isMobileActive, setisMobileActive] = useState(false);
const onClick = () => setIsActive(!isActive);
const onLogout = () => {
dispatch(logout())
}
return (
<nav className="navbar" role="navigation" aria-label="main navigation">
<div className="navbar-brand">
<a className="navbar-item" href="https://bulma.io">
<img
src="https://bulma.io/images/bulma-logo.png"
width="112"
height="28"
/>
</a>
<a
onClick={() => {
setisMobileActive(!isMobileActive)
}}
role="button"
className={`navbar-burger burger ${isActive ? "is-active" : ""}`}
aria-label="menu"
aria-expanded="false"
data-target="navbarBasicExample"
>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="navbarBasicExample" className="navbar-menu">
<div className="navbar-end">
<a className="navbar-item">Dashboard</a>
<div
onClick={onClick}
ref={dropdownRef}
className={`navbar-item has-dropdown ${
isActive ? "is-active" : ""
}`}
>
<a className="navbar-link">Account</a>
<div className="navbar-dropdown is-right">
<a className="navbar-item">Account settings</a>
<a className="navbar-item">Set Job filters</a>
<a className="navbar-item">Report an issue</a>
<a className="navbar-item" onClick={onLogout}>Log out</a>
</div>
</div>
</div>
</div>
</nav>
);
};
The most bottom part with dropdown is for desktop nav bar. What is missing for mobile toggle menu. How can I fix it? Who I click the toggle button nothing happens.
I‘m not familiar with React, but on the bulma side you need to toggle the class is-active on both the navbar-burger and the targeted navbar-menu.
There are implementation examples in Bulma navbar documentation, personally I'm using the jQuery implementation which works perfectly :
$(document).ready(function() {
// Check for click events on the navbar burger icon
$(".navbar-burger").click(function() {
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
$(".navbar-burger").toggleClass("is-active");
$(".navbar-menu").toggleClass("is-active");
});
});
but there's also a Vanilla Javascript implementation in the docs if you want.
I have added bulma.css in my Next.js project and all runs well, but navbar toggle doesn't work because need add some pure javascript code and React doesn't provide pure DOM events
Just add React Lifecycle event and put your code.
ORIGINAL example:
import React from "react";
class NavBar extends React.Component {
componentDidMount() {
const $navbarBurgers = Array.prototype.slice.call(
document.querySelectorAll(".navbar-burger"),
0
);
if ($navbarBurgers.length > 0) {
// Add a click event on each of them
$navbarBurgers.forEach(el => {
el.addEventListener("click", () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle("is-active");
$target.classList.toggle("is-active");
});
});
}
}
render() {
return (
<nav className="navbar" role="navigation" aria-label="main navigation">
<div className="navbar-brand">
<a className="navbar-item" href="https://bulma.io">
<img
src="https://bulma.io/images/bulma-logo.png"
width="112"
height="28"
/>
</a>
<a
role="button"
className="navbar-burger burger"
aria-label="menu"
aria-expanded="false"
data-target="navbarBasicExample"
>
<span aria-hidden="true" />
<span aria-hidden="true" />
<span aria-hidden="true" />
</a>
</div>
<div id="navbarBasicExample" className="navbar-menu">
<div className="navbar-start">
<a className="navbar-item">Home</a>
<a className="navbar-item">Documentation</a>
<div className="navbar-item has-dropdown is-hoverable">
<a className="navbar-link">More</a>
<div className="navbar-dropdown">
<a className="navbar-item">About</a>
<a className="navbar-item">Jobs</a>
<a className="navbar-item">Contact</a>
<hr className="navbar-divider" />
<a className="navbar-item">Report an issue</a>
</div>
</div>
</div>
<div className="navbar-end">
<div className="navbar-item">
<div className="buttons">
<a className="button is-primary">
<strong>Sign up</strong>
</a>
<a className="button is-light">Log in</a>
</div>
</div>
</div>
</div>
</nav>
);
}
}
export default NavBar;
I had the same issue and in my case I can resolve it adding in the _app component this line
import 'bulma/css/bulma.css
I have the following code in my React render function:
<div ref="btnGroup" className="dropdown">
<button class="dropdown-toggle" data-toggle="toggle" onClick={this.toggleDropdown}></button>
<ul class="scrollable-menu-parent dropdown-menu">
<div>
<form class="droplist-panel">
<input class="droplist-search" />
<div class="scrollable-menu">
<li class="dropdown-item"> </li>
...
...
</div>
</form>
</div>
</ul>
</div>
In the toggle dropdown function, I am adding the open class to the topmost div.
However, the <ul> is not getting the auto dropdown style when it is open, the width is way larger and the positioning is also incorrect.
Am I doing something wrong here with the dropdown, dropdown-toggle and dropdown-menu which is causing the <ul> to not get correct classes?
Edit:
toggleDropdown() {
const $el = $(this.refs.btnGroup);
if ($el.is('.open')) {
this.closeDropdown($el);
}
else {
this.openDropdown($el);
}
},
closeDropdown(ele) {
ele.removeClass('open');
this.clearState();
},
openDropdown(ele) {
ele.addClass('open');
if (this.props.onOpen) {
this.props.onOpen.bind(this)();
}
},