Hi I'm new to ReactJS so I'm importing some work of mine to my project and turning it into components. I have a span acting as a button with keyframe animations, but when i load the page it gets animated.
One solution i have is to make a .class.animation and give the .animation class on the first click.
The thing is that I know how to code it in jquery but not on react.
The idea is to convert this into react:
$('.navTrigger').onClick(function () {
$(this).addClass('animations');
});
Right now I have this:
const [isActive, setActive] = useState("false");
const handleToggle = () => {
setActive(!isActive);
};
return (
<span onClick={handleToggle} className={`navTrigger ${isActive ? "" : "animations"} ${isActive ? "" : "active"}`}>
<i></i>
<i></i>
<i></i>
</span>
);
I have a function where i toggle the active class to run backward and forward animations.
What the code below does is on web load, the span starts with navTrigger class. The first time you click it its's given animations and active class. And then if you interact with it again it takes out active class and leaves animations there
function MenuButton() {
const [isActive, setActive] = useState(false);
const [animating, setAnimating] = useState(false);
const handleToggle = () => {
setActive(!isActive);
setAnimating(true);
};
return (
<span onClick={handleToggle} className={`navTrigger ${animating ? "animations" : ""} ${isActive ? "active" : ""}`}>
<i></i>
<i></i>
<i></i>
</span>
);
}
Related
I have a multi page form that renders a list of buttons for each possible answer.
I am currently using getElementByID to change the button style when a button is clicked. I think this is not considered good practice in react.
can I use the useRef hook to target the DOM element and change its style instead of using getElementByID if the buttons are dynamically displayed with map?
{answers.map((answer, count = 0) => {
return (
<Button
key={count}
id=`button${count}`
onClick={(e) => {
document.getElementById(`${e.currentTarget.id}`).style.color = "white";
}}
>
<ButtonTitle>{answer.name}</ButtonTitle>
</Button>
);
})}
(animations on safari are breaking the active style, so I can't use the active pseudo element)
You can do this by adding a new state and toggle active class by that state.
Code something like this.
const [activeindex, setActiveIndex] = useState("");
return(
<>
{answers.map((answer, count = 0) => {
return (
<Button
key={count}
className={count==activeindex?"acvie":""}
onClick={(e) => {
setActiveIndex(count)
}}
>
<ButtonTitle>{answer.name}</ButtonTitle>
</Button>
);
})}
}
</>
And use .active class in css file.
I am trying to change a div's visibility from hidden to visible using button click. But even when I am clicking the button, the visibility is not changing. I have logged the console after the clickHandler, and it still says false even after I set it to true inside the function. So far, I have this,
let clicked = false;
//change image on fortune cookie click
const clickHandler = (e) => {
e.target.setAttribute(
"src",
"https://i.ibb.co/cksx7kr/kisspng-fortune-cookie-drawing-clip-art-fortune-cookie-5b237469209879-9079770415290502171335.png"
);
clicked = true;
};
console.log(clicked);
return (
<div className="App">
<button onClick={clickHandler}>
<img
className="cookie"
src="https://i.ibb.co/9YQV2qq/kisspng-fortune-cookie-biscuits-bakery-drawing-clip-art-fortune-cookies-5b0ec5e3013c23-3980054715276.png"
/>
</button>
<div
className="fortuneMessage"
style={{ visibility: clicked ? "visible" : "hidden" }}
>
{fortune}
</div>
</div>
);
When you are using React, you need a state in order to have a DOM update. That would fork for you (don't forget to import useState at the top of your file) :
const [clicked, setClicked] = useState(false);
const [src, setSrc] = useState("https://i.ibb.co/9YQV2qq/kisspng-fortune-cookie-biscuits-bakery-drawing-clip-art-fortune-cookies-5b0ec5e3013c23-3980054715276.png");
//change image on fortune cookie click
const clickHandler = (e) => {
setSrc("https://i.ibb.co/cksx7kr/kisspng-fortune-cookie-drawing-clip-art-fortune-cookie-5b237469209879-9079770415290502171335.png");
setClicked(true);
};
console.log(clicked);
return (
<div className="App">
<button onClick={clickHandler}>
<img
className="cookie"
src={src}
/>
</button>
<div
className="fortuneMessage"
style={{ visibility: clicked ? "visible" : "hidden" }}
>
{fortune}
</div>
</div>
);
You'll need to use state instead of the plain clicked variable.
const [clicked, setClicked] = useState(false);
Call the setState function inside the clickHandler function instead of setting clicked to true.
setClicked(true);
in React, the variable is not two way binding.
The clicked variable in your function will only get to be true in the function itself but not outside the function
So in this case you need to use useState so that the clicked state will be re-rendered again with updated boolean
const [clicked, setClicked] = useState(false)
const clickHandler = () => {
setClicked(true)
}
so that your clicked variable will be updated, hence the css will be updated again.
for more reference with useState can check their documentation https://reactjs.org/docs/hooks-state.html
I am trying to add the class sub-menu-open to a li when its clicked which will then open a submenu. however the li's are dynamically generated and theres about 6 of them. When i click on an li its successfully adding the class to the li however its adding the class to all the li's now just the one clicked. Can yall help me figure out how to get the class to only stick the the li thats clicked?
const [isActive, setActive] = useState(false);
const toggleClass = () => {
setActive(!isActive);
};
return (
<>
{menus.map((menuItem, i) => {
return (
<li className={"mobile-menu-item menu-item-has-children" + (isActive? ' sub-menu-open': null)} onClick={toggleClass}>
...
Update the li
<li
className={"mobile-menu-item menu-item-has-children" + (
isActive == i
? ' sub-menu-open'
: null
)}
onClick={() => toggleClass(i)}>
Then update the function like bellow
const toggleClass = (index) => {
setActive(index);
};
Now update the state like bellow
const [isActive, setActive] = useState(null);
i am using a functional component, and have created a sidebar menu structure , with parent child way (kind of dropdown). So when I click on parent an active class should be toggle and on its next element toggle style> display> none/block.
<Fragment key={index}>
<button
className='dropdown-btn bg-transparent haschild'
style={{ border: 'none' }}
>
{data.name} <i className='fas fa-chevron-right'></i>
</button>
<div
className='dropdown-container'>
<Content
config={menuItem.children}
children={true}
/>
</div>
</Fragment>
and on use effect
useEffect(() => {
var dropdown = document.getElementsByClassName("haschild");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function () {
this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display == "none") {
dropdownContent.style.display = "block";
} else {
dropdownContent.style.display = "none";
}
});
}
},[]);
wherever i have class has child
on that element i have to toggle a class active
and on its next siblings , want to add style attr with display
When using a Framework like react that doesn't directly manipulate the DOM it's not recommended to change style like that.
What you should do instead is to either work with classes and toggle them in react, not using document.getElementsByClassName or similar functions.
This could look something like this, depending on your need:
const ToggleButton = () => {
const [active, setActive] = useState(false);
return (
<button onClick={() => setActive(prev => !prev)} className={active ? 'active' : 'inactive'}>
Toggle active
</button>
);
};
This component would render a button that can be clicked to toggle between the classes active and inactive. The rest can and perhaps should be done with purely CSS.
Modern CSS combinators like ~ can be used to affect following elements. You can read more about CSS combinators here
I am rendering a map of buttons in react to toggle the is-active class. But if i click one of them, all of them are opened. How can i check if only the clicked button toggles the class?
In plain javascript something like this feels much easier. thanks guys!
const [open, setOpen] = useState(false)
<div
id={"id" + node.id}
key={node.id}
className={`dropdown ${open ? "is-active" : ""}`}
onClick={() => setOpen(!open)}
>
Of course all will be active. You need to place an id to state in order to check which button is clicked.
<div
className="dropdown"
id={"id" + node.id}
key={node.id}
className={`dropdown ${open === node.id ? "is-active" : ""}`}
onClick={() => setOpen(node.id)}
>
You can extract your button to component and change it local state when button is clicked.
function Button(props) {
const [open, setOpen] = useState(false)
return (
<div
className="dropdown"
id={"id" + node.id}
key={node.id}
className={`dropdown ${open ? "is-active" : ""}`}
onClick={() => setOpen(!open)}
>MyButton</div>
)
}