Using localStorage to keep css style in react after page reload - css

I would like to use localStorage to store a css style :focus for my elements. Currently when I click on component in my Dropdown it toggles green color, but when I click outside of it or I reload page, it disappears. Check the screenshot below.
How I can implement here localStorage to save :focus after page reload or maybe there is even better way of doing that which I don't know?
My Menu
const DropdownMenu = (props) => {
let companyElements = props.state.companies.map(c => (
<DropdownItem key={c.id} name={c.name} owner={c.owner} id={c.id} /> ));
return (
<div className="dropdown">
{companyElements}
</div>
);
}
My Item
const NavItem = (props) => {
const [open, setOpen] = useState(false);
return (
<div>
<li className="nav-item">
<a href="#" className="icon-button"
onClick={() => setOpen(!open)}>
{props.state.companies[0].name}
</a>
{open && props.children}
</li>
</div>
);
}
Style
.menu-item:focus{
background-color: green;
}

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>

How to change overflow style to hidden when modal opens

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>
);
}

Add and remove classes in React

How can I add/ remove a className on click to change the style of some component?
I want to rotate the arrow on the right when I click on it and display: none; all the components beside it.
I also want to add do the same thing when I hit the mobile breakpoint
const [isRotated, setIsRotated] = useState(false);
handleClick() {
setIsRotated(true)
}
<button className={isRotated && 'rotate-class'} onClick={handleClick} />
{ !isRotated && <Element/>} // this will hide the element when clicked on the button
This would a better approach then setting display: none on the other elements, but if you must do that, do this:
<Element style={{ display: isRotated ? 'none': 'block' }} /> // I'm guessing the default style of display is 'block' of the elements you want to hide
You can add boolean state and function for change state same this code.
function App() {
const [state, setState] = useState(true);
const rotateHandler = () => {
setState(() => !state);
};
return (
<div className="App">
{/* button for change state */}
<button onClick={rotateHandler}>click for rotate and hide</button>
{/* icon for rotate */}
<div>
<FontAwesomeIcon
icon={faAngleRight}
style={{
transform: state ? "rotate(90deg)" : "rotate(0deg)"
}}
/>
</div>
{/* text hide when */}
<div style={{ display: state ? " block" : "none" }}>
<div>text hide after state is false</div>
<div>you can click on button</div>
<div>for rotate arrow icon</div>
<div>and hide this text</div>
</div>
</div>
);
}
I add conditions in inline style, but you can add conditions on className
className={state ? "show" : "hide"}

Removing class from last clicked event in React

I have a Navbar with tabs, and I want to make a function called onClick that gets the event, and adds a class to that tab "active". But, when I click another tab, it should remove a class from the previous tab and add it to that one.
Sample of my code:
const [clickedTab, setClickedTab] = useState(true);
function Click() {
if (clickedTab === true) {
console.log(clickedTab);
tab.classList.add("active");
}
else {
console.log("Error!");
}
}
In React use the model (via useState() in this case) to make changes to the view.
Set the activeId of the tab in the state, and if the tab's id is equal to activeId pass set it's active to true. The tab itself can add/remove the className.
const { useState } = React;
const Tab = ({ id, active, setActive }) => (
<li
className={`tab ${active ? 'active' : ''}`}
onClick={() => setActive(id)}
>
{id}
</li>
);
const Example = ({ tabs }) => {
const [activeId, setActive] = useState();
return (
<ul className="tabs">
{tabs.map(id => (
<Tab
key={id}
id={id}
setActive={setActive}
active={id === activeId}
/>
))}
</ul>
);
}
const tabs = [1, 2, 3, 4];
ReactDOM.render(
<Example tabs={tabs} />,
root
);
.tabs {
display: flex;
list-style: none;
}
.tab {
height: 1em;
width: 2em;
border: 1px solid red;
text-align: center;
cursor: pointer;
}
.active {
background: red;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="root"></div>
Here is a simple example so you can get the idea; we hold current active element id in a state then based on that we decide what class name it should have; no need to use classList's add or remove
function Header () {
const [active, setActive] = React.useState();
return (
<header>
<ul>
<li
className={active === 1? "red":"blue"}
onClick={()=>setActive(1)}
>a</li>
<li
className={active === 2? "red":"blue"}
onClick={()=>setActive(2)}
>b</li>
<li
className={active === 3? "red":"blue"}
onClick={()=>setActive(3)}
>c</li>
</ul>
</header>
);
}
ReactDOM.render( <Header />, app );
.red{background:red}.blue{background:blue}li{color:#fff;width:30px}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

How can I use window.scrollby with react?

I am trying to click a button which scrolls down to a specific portion of my app. So currently I have:
class Nav extends Component {
foo(){
console.log('baz')
window.scrollTo(0, 100);
}
render() {
return (
<nav>
<a href="#" onClick={()=> this.foo()}>About</a>
</nav>
);
}
}
This will console.log "baz" but won't scroll down to 100
Remove the
href="#"
This is causing the link to link the top of the page
You can do like this -
const handleRef = (param) => window.scrollTo(0, param);
<p onClick={()=> handleRef(1000)} >Drops</p>
import react from "react";
const Stchange = ()=>{
const dev = ()=>{
window.scrollBy(0,50);
}
return(
<>
<button onClick={dev}>Scroll</button>
<h1>There are man struc Lorem Ipsum which looks reasonable. The</h1>
</>
)
}
export default Stchange;
We have to prevent the default action of the anchor tag using event.preventDefault() method and change href="#" to href="/" in anchor tag
class Nav extends Component {
foo(event){
event.preventDefault();
console.log('baz')
window.scrollTo(0, 100);
}
render() {
return (
<nav>
<a href="/" onClick={(event)=> this.foo(event)}>About</a>
</nav>
);
}
}

Resources