How to change overflow style to hidden when modal opens - css

I am trying to create react app and i want overflow to hidden when button is pressed,
i want to display contact form on modal but overflow is running everything i can scroll even with modal is open
Here is my navbar with button
import React from "react";
import { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { FaBars, FaTimes } from "react-icons/fa";
import "./Navbar.css";
import { IconContext } from "react-icons/lib";
import Button from "./Button";
import Modal from "./Contact Form/Modal";
import { motion, AnimatePresence } from "framer-motion";
export default function Navbar() {
const [click, setClick] = useState(false);
const [button, setButton] = useState(true);
const [modalOpen, setModalOpen] = useState(false);
function closeModal() {
setModalOpen(false);
}
function openModal() {
setModalOpen(true);
}
function handleClick() {
setClick(!click);
}
function closeMobileMenu() {
setClick(false);
}
function showButton() {
if (window.innerWidth <= 960) {
setButton(false);
} else {
setButton(true);
}
}
function closeMobileMenu() {
setClick(false);
}
useEffect(() => {
showButton();
}, []);
window.addEventListener("resize", showButton);
return (
<>
<IconContext.Provider value={{ color: "#fff" }}>
<div className="navbar">
<div className="navbar-container container">
<Link to="/" className="navbar-logo" onClick={closeMobileMenu}>
LOGO
</Link>
<div className="menu-icon" onClick={handleClick}>
{click ? <FaTimes /> : <FaBars />}
</div>
<ul className={click ? "nav-menu active" : "nav-menu"}>
<li className="nav-item">
<Link to="/" className="nav-links" onClick={closeMobileMenu}>
Home
</Link>
</li>
<li className="nav-item">
<Link to="/" className="nav-links" onClick={closeMobileMenu}>
About Us
</Link>
</li>
<li className="nav-item">
<Link to="/" className="nav-links" onClick={closeMobileMenu}>
Contact Us
</Link>
</li>
{/* Main button */}
<li className="nav-btn">
{button ? (
<Link to='' className="btn-link">
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
className="btn--outline"
onClick={() => (modalOpen ? closeModal() : openModal())} //modal opens
>
CONTACT US
</motion.button>
</Link>
) : (
<Link
to=""
className="btn-link"
onClick={closeMobileMenu}
>
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
className="btn--mobile"
buttonSize='btn--mobile'
buttonStyle='btn--outline'
onClick={() => {(modalOpen ? closeModal() : openModal())}} //modal opens
>
Contact US
</motion.button>
</Link>
)}
</li>
</ul>
</div>
</div>
<AnimatePresence
// Disable any initial animations on children that
// are present when the component is first rendered
initial={false}
// Only render one component at a time.
// The exiting component will finish its exit
// animation before entering component is rendered
exitBeforeEnter={true}
// Fires when all exiting nodes have completed animating out
onExitComplete={() => null}
>
{modalOpen && <Modal modalOpen={modalOpen} handleClose={closeModal} />}
</AnimatePresence>
</IconContext.Provider>
</>
);
}
I was trying to do it use State but it didn't work. I use style effect but i didn't manage to achieve it

You will make a boolean state with an initial value set to false.
When the button is clicked you will update the state from false to true and I will recommend it for you instead of making it true. then you will use this state easily with your style property and do what you need.
change the style bellow based on your needs.
import { useState } from "react";
export default function App() {
const [clicked, setClicked] = useState(false);
return (
<div className="App">
<h1 style={{ display: clicked ? "none" : "block" }}>Hello
CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={() => setClicked(!clicked)}>click</button> <= here instead of making it true. I made it the oppesite of the previous value. to toggle between them.
</div>
);
}

Related

How to add a class on click, and remove the same class from all other elements?

I have a button navigation and when you click on a button, the active class is added. My goal is for the active class to be added to the button clicked, but remove that class of active on all other buttons if present. The 'About' button will have a class of active on page load.
Not sure how to translate this to React, in JavaScript on click I would remove the class from all the elements in a loop and add a class to the target clicked if it did not already have the active class.
Code Sandbox - https://codesandbox.io/s/toggle-active-on-class-clicked-remove-from-the-rest-r467l1?file=/src/App.js
export default function Header() {
const [active, setActive] = useState(true);
const toggleColor = function (e) {
// on load, 'About' button has active class
// when clicking another menu item add active class, remove active from the rest of buttons
console.log(e.target);
};
return (
<header className="header-img-container">
<nav>
<ul>
<li>
<button onClick={toggleColor} className={active ? "active" : ""}>
About
</button>
</li>
<li>
<button onClick={toggleColor}>Skills</button>
</li>
<li>
<button onClick={toggleColor}>Projects</button>
</li>
<li>
<button onClick={toggleColor}>Words</button>
</li>
</ul>
</nav>
</header>
);
}
There are so many ways to solve that problem. You can try this if it's meet your requirements.
import "./styles.css";
import { useState } from "react";
const list = ["About", "Skills", "Projects", "Words"];
export default function Header() {
const [activeLink, setActiveLink] = useState("About");
return (
<header className="header-img-container">
<nav>
<ul>
{list.map((item) => (
<li key={item}>
<button
onClick={() => setActiveLink(item)}
className={activeLink === item ? "active" : ""}
>
{item}
</button>
</li>
))}
</ul>
</nav>
</header>
);
}
Create a state like this
const [active, setActive] = useState({About: true, Skills: false, Projects: false, Words: false})
А change local parameter to add a class to element. For example
<li>
<button onClick={() => {
setActive({...active, About: false, Skills: true, Projects: false,
Words: false })
}}>Skills</button>
</li>
There are many possible approaches, here is a basic example that uses an object type active state to store the value for each list item.
const [active, setActive] = useState({ About: true })
The list data is stored in an array so it can be mapped in the JSX part of the component.
const itemList = ["About", "Skills", "Projects", "Words"]
While index is not an ideal key it is used here just for example purpose.
{
itemList.map((item, index) => (
<li key={index}>
<button
onClick={() => toggleColor(item)}
className={active[item] ? "active" : ""}
>
{item}
</button>
</li>
));
}
toggleColor sets value for active, and it specify that active should always be in the format of {About: true}, {Skills: true} and such. The !!! covers the case when certain keys are not existing in the object.
const toggleColor = function (item) {
setActive((prev) => {
return { [item]: !!!prev[item] };
});
};
Below is the full example, it runs in the snippet for convenience.
function Header() {
const [active, setActive] = React.useState({ About: true });
const itemList = ["About", "Skills", "Projects", "Words"];
const toggleColor = function (item) {
// on load, 'About' button has active class
// when clicking another menu item add active class, remove active from the rest of buttons
setActive((prev) => {
return { [item]: !!!prev[item] };
});
};
return (
<header className="header-img-container">
<nav>
<ul>
{itemList.map((item, index) => (
<li key={index}>
<button
onClick={() => toggleColor(item)}
className={active[item] ? "active" : ""}
>
{item}
</button>
</li>
))}
</ul>
</nav>
</header>
);
}
const App = () => {
return (
<div>
<Header />
</div>
);
};
ReactDOM.render(<App />, document.querySelector("#root"));
.App {
font-family: sans-serif;
text-align: center;
}
button {
padding: 6px;
}
.active {
border: 1px solid pink;
color: hotpink;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>

Failed prop type: Invalid prop `className` of type 'function'

I am making a Navbar for my dashboard but encountered this error which says I should pass a string to className and not function . I am passing the function to className as I have to check if the navbar is open or not. How can I solve this error?
Here is my code for navbar:
//STYLES
import styles from "./Navbar.module.scss";
import React from 'react';
//CONTEXT
import { useContext } from "react";
import NavContext from "../../context/NavContext";
//REACT ROUTER
import { NavLink } from "react-router-dom";
//ICONS
import {
MdOutlineDashboard,
MdOutlineAnalytics,
MdOutlinedFlag,
MdPeopleOutline,
MdOutlineMessage,
MdOutlineLogout,
} from "react-icons/md";
import { FaTimes } from "react-icons/fa";
import { BsThreeDots } from "react-icons/bs";
import { VscDashboard } from "react-icons/vsc";
const NavUrl = ({ url, icon, description }) => {
const { nav, setNav } = useContext(NavContext);
const checkWindowSize = () => {
if (window.innerWidth < 1024) setNav(!nav);
};
return (
<li className={styles.li_navlink}>
<NavLink
to={`${url}`}
className={({ isActive }) => (isActive ? styles.active : undefined)}
onClick={() => checkWindowSize()}
>
{icon}
<span className={styles.description}>{description}</span>
</NavLink>
</li>
);
};
const Navbar = () => {
const { nav, setNav } = useContext(NavContext);
return (
<div
className={`${styles.navbar_container} ${
nav ? styles.navbar_mobile_active : undefined
}`}
>
<nav className={nav ? undefined : styles.nav_small}>
{/* LOGO */}
<div className={styles.logo}>
<VscDashboard className={styles.logo_icon} />
<FaTimes
className={styles.mobile_cancel_icon}
onClick={() => {
setNav(!nav);
}}
/>
</div>
{/* MENU */}
<ul className={styles.menu_container}>
{/* FIRST CATEGORY */}
<span className={styles.categories}>
{nav ? "Pages" : <BsThreeDots />}
</span>
<NavUrl
url="/"
icon={<MdOutlineDashboard />}
description="Dashboard"
/>
<NavUrl
url="usage"
icon={<MdOutlineAnalytics />}
description="Usage"
/>
<NavUrl
url="plan"
icon={<MdOutlinedFlag />}
description="Plan"
/>
<NavUrl url="documentation" icon={<MdPeopleOutline />} description="Documentation" />
<NavUrl
url="invoices"
icon={<MdOutlineMessage />}
description="Invoices"
/>
</ul>
{/* LOGOUT BUTTON */}
<div
className={`${styles.btn_logout}`}
onClick={() => {
setNav(!nav);
}}
>
<MdOutlineLogout />
</div>
</nav>
<div
className={nav ? styles.mobile_nav_background_active : undefined}
onClick={() => {
setNav(!nav);
}}
></div>
</div>
);
};
export default Navbar;
Here is my error which is saying to pass string in navlink , navurl ,ul , nav , navbar , div , App , route , switch , router , browserRouter classes :
index.js:1 Warning: Failed prop type: Invalid prop `className` of type
`function` supplied to `NavLink`, expected `string`.
in NavLink (at Navbar.jsx:33)
in NavUrl (at Navbar.jsx:73)
in ul (at Navbar.jsx:67)
in nav (at Navbar.jsx:54)
in div (at Navbar.jsx:49)
in Navbar (at App.jsx:24)
in div (at App.jsx:21)
in App (at src/index.js:19)
in Route (at src/index.js:19)
in Switch (at src/index.js:18)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.js:17)
I think you do it in the last div you have
<div
className={nav ? styles.mobile_nav_background_active : undefined}
onClick={() => {
setNav(!nav);
}}
></div>
may be you must use onMouseEnter
onMouseEnter={() => {
setisActive (true);
}}
onMouseLeave={() => {
setisActive (false);
}}
className={isActive ? styles.active : undefined}

How do i bind a css stylesheet to only 1 react component?

I am using a React Template, where i inserted a shopping cart site using some react and Simple HTML (The code is below the question). Also i have a index.css file, which contains the css for the shopping cart. My goal is to implement the css only in the shopping cart site.
I tried to "import './index.css' inside my shopping cart.
The problem was as follows: After rendering the shopping cart, the css was applied to every other site as well.
How is it possible to use the css code only in the shopping cart?
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link } from 'react-router-dom';
import { addToCart, removeFromCart } from '../../frontend/actions/cartActions';
import MessageBox from '../../frontend/MessageBox';
import { useLocation } from 'library/hooks/useLocation';
export default function CartScreen(props) {
// Namen
var a = window.location.href;
var b = a.substring(a.indexOf("?")+1)
const productId = b;
console.log(productId)
// redux store
const cart = useSelector((state) => state.cart);
const { cartItems, error } = cart;
const dispatch = useDispatch();
useEffect(() => {
if (productId) {
dispatch(addToCart(productId));
}
}, [dispatch, productId]);
const removeFromCartHandler = (id) => {
// delete action
dispatch(removeFromCart(id));
};
const checkoutHandler = () => {
props.history.push('/signin?redirect=shipping');
};
return (
<div className="row top">
<div className="col-2">
<h1>Shopping Cart</h1>
{error && <MessageBox variant="danger">{error}</MessageBox>}
{/* display cart or message if empty */}
{cartItems.length === 0 ? (
<MessageBox>
Cart is empty. <Link to="/">Go Shopping</Link>
</MessageBox>
) : (
<ul>
{cartItems.map((item) => (
<li key={item.product}>
<div className="row">
<div>
<img
src={item.image}
alt={item.name}
className="small"
></img>
</div>
<div className="min-30">
<Link to={`/product/${item.product}`}>{item.name}</Link>
</div>
<div>
<select
value={item.qty}
onChange={(e) =>
dispatch(
addToCart(item.product, Number(e.target.value))
)
}
>
{[...Array(item.countInStock).keys()].map((x) => (
<option key={x + 1} value={x + 1}>
{x + 1}
</option>
))}
</select>
</div>
<div>${item.price}</div>
<div>
<button
type="button"
onClick={() => removeFromCartHandler(item.product)}
>
Delete
</button>
</div>
</div>
</li>
))}
</ul>
)}
</div>
<div className="col-1">
<div className="card card-body">
<ul>
<li>
<h2>
Subtotal ({cartItems.reduce((a, c) => a + c.qty, 0)} items) : $
{cartItems.reduce((a, c) => a + c.price * c.qty, 0)}
</h2>
</li>
<li>
<button
type="button"
onClick={checkoutHandler}
className="primary block"
disabled={cartItems.length === 0}
>
Proceed to Checkout
</button>
</li>
</ul>
</div>
</div>
</div>
);
}
import './index.css'
give the div in the html a specific name: <div className="cartScreen">
in css, specify the element where the style should be used:
body .cartScreen{
margin: 0;
height: 100vh;
font-size: 1.6rem;
font-family: Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

props is undefined when passing from parent to component in next js

I have /pages/profile.js which calls the LovedOne element, passing values from props.
Debugging shows that these values are valid when passed
import React from "react";
import LovedOne from "../components/loved_one";
export const Profile = ({ loved_ones }) => {
const [session, loading] = useSession();
if (loading) return <div>loading...</div>;
if (!session) return <div>no session</div>;
return (
<Layout>
{session && (
<>
<img src={session.user.image} className="avatar" />
<h1>{session.user.name}</h1>
</>
)}
{loved_ones.map((loved_one, index) => (
<LovedOne
key={index}
firstname={loved_one.firstname}
surname={loved_one.surname}
email={loved_one.email}
/>
))}
<style jsx>{`
.avatar {
width: 220px;
border-radius: 10px;
}
`}</style>
</Layout>
);
};
However in /components/loved_one.js my props is undefined
import React, { useState, useRef } from "react";
export const LovedOne = ({ props }) => {
const [setActive, setActiveState] = useState("");
const [setHeight, setHeightState] = useState("0px");
const content = useRef();
function toggleAccordion() {
setActiveState(setActive === "" ? "active" : "");
setHeightState(
setActive === "active" ? "0px" : `${content.current.scrollHeight}px`
);
}
return (
<div>
<div className="row">
<button
className={`collection-item ${setActive}`}
onClick={toggleAccordion}
>
<i className="fas fa-plus teal-text"></i>
</button>
<div className="col s2">
{props.firstname} {props.surname}
</div>
<div className="col s2">{props.email}</div>
</div>
<div ref={content} style={{ maxHeight: `${setHeight}` }}>
<span>some stuff</span>
</div>
</div>
);
};
export default LovedOne;
I've tried passing single variables, and passing the entire loved_ones object. I get the same problem.
Any help much appreciated!
Have you tried passing props instead of {props} ?
lose brackets, try this way:
export const LovedOne = (props) => {

Semantic-UI-React not applied using Nextjs _app.js

I am using Nextjs, Semantic-UI-React, next-routes and Auth-0
In the _app.js file contains both the Head tag and the Layout component. The semantic.min.css link which is injected under the Head tag in _app.js doesn't seem to work. The css styling is not applied at all.
My workaround is to wrap all my other pages with the Layout component and the Head tag is injected inside the Layout component. However, I prefer to apply the Layout wrapper component and Head tag inside _app.js so I need not apply them in every page
Anyone knows how to resolve this? Thanks
_app.js
export default class MyApp extends App {
static async getInitialProps(c) {
const pageProps = await App.getInitialProps(c);
return { ...pageProps };
}
render() {
const { Component, pageProps } = this.props;
return (
<Layout>
<h2>Test</h2>
<Head>
<title>CyberCoin</title>
<meta
name="viewport"
content="initial-scale=1.0, width=device-width"
/>
<link
rel="stylesheet"
href="//cdn.jsdelivr.net/npm/semantic-ui#2.4.2/dist/semantic.min.css"
/>
</Head>
<Component {...pageProps} />
</Layout>
);
}
}
index.js
export default class Auth extends Component {
render() {
return (
<div>
{auth0.isAuthenticated() && (
<div>
<Link route="/main">
<a className="item">Main</a>
</Link>
</div>
)}
{!auth0.isAuthenticated() && (
<div>
<Link route="/about">
<a className="item">About</a>
</Link>
</div>
)}
{!auth0.isAuthenticated() && (
<div>
<Button onClick={auth0.login} primary>
Authorize
</Button>
</div>
)}
{auth0.isAuthenticated() && (
<div>
<Button onClick={auth0.logout} primary>
Exit
</Button>
</div>
)}
</div>
);
}
}
main.js
class CampaignIndex extends React.Component {
static async getInitialProps() {
const campaigns = await factory.methods.getDeployedCampaigns().call();
return { campaigns };
}
renderCampaigns() {
const items = this.props.campaigns.map(address => ({
header: address,
description: (
<Link route={`/campaigns/${address}`}>
<a>View Campaign</a>
</Link>
),
fluid: true
}));
return <Card.Group items={items} />;
}
render() {
return (
<div>
<div>
<h3>Open Campaigns</h3>
<Link route="/campaigns/new">
<a>
<Button
floated="right"
content="Create Campaign"
icon="add circle"
primary
/>
</a>
</Link>
{this.renderCampaigns()}
</div>
</div>
);
}
}
export default CampaignIndex;

Resources