'How to hide an element using useState and classList manipulation - React
I am trying to create a way of toggling on and off certain elements of an svg that is being used across a design, so it is reusable across the website.
To be more specific I am trying to create a toggle that will hide the red line part of the svg by entering "false" into the setter prop - so across the project this can be done where needed.
I am using useState and a sort of props system to try and achieve this however I am having trouble around the specifics - the current error I get is "ReferenceError: setter is not defined".
Is there a better way to achieve this? and what way would I go about it so setter is defined and my current approach would work?
Code below:
const LineSvg = ({setter, toggle}) => {
return(
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 59.6 830" xmlSpace="preserve" className="capsules capsules-image-bottom-right position-absolute">
<path id="red-line" toggle={toggle} setter={setter} className="capsule-a capsule-foreground fill-red track-on-scroll" d="M10.4,257.6A10.39,10.39,0,0,1,20.8,268V584.4a10.4,10.4,0,0,1-20.8,0V267.9A10.37,10.37,0,0,1,10.4,257.6Z" />
<g className="track-on-scroll">
<path id="green-line" d="M49.2,394.7a10.39,10.39,0,0,1,10.4,10.4v84.4a10.4,10.4,0,0,1-20.8,0V405.1A10.33,10.33,0,0,1,49.2,394.7Z" className="capsule-b fill-green" />
<path id="blue-line" d="M49.2,354.6A10.39,10.39,0,0,1,59.6,365v4.9a10.4,10.4,0,1,1-20.8,0v-5A10.31,10.31,0,0,1,49.2,354.6Z" className="capsule-c fill-blue" />
<path id="grey-line" d="M49.2,235.2a10.39,10.39,0,0,1,10.4,10.4V330a10.4,10.4,0,0,1-20.8,0V245.6a10.33,10.33,0,0,1,10.4-10.4Z" className="capsule-d fill-grey-light" />
</g>
</svg>
)
}
export default LineSvg;
index.jsx
const HomePage = () => {
const [redToggle, setRedToggle] = useState(true);
if(setter == "false"){
setRedToggle(false)
} else if(setter == "true"){
setRedToggle(true)
}
const onToggle = () => {
const redLine = document.getElementById("red-line");
if(redToggle === false){
redLine.classList.add("capsule-hide")
} else if(redToggle === true){
redLine.classList.remove("capsule-hide")
}
}
return(
<Layout>
<Hero
text={
<h1>If your software goals aren't ambitous, don't bother scrolling.</h1>
}
image={
//If nothing is to go in here empty "" needed to prevent error
""
}
/>
<section className="dark-grey-section py-10">
<Container>
<Row>
<Col sm={12} md={6}>
<div className="text-column">
<h5>What we do</h5>
<h4><strong>Thrive in the era of software advantage</strong></h4>
<p>Today’s users aren’t easily impressed.</p>
<p>And what it does take to impress them can be insanely difficult to build.</p>
<p>Insanely difficult happens to be our speciality.</p>
<p>Lineate helps businesses craft the software that fits their ambitious needs—quickly, reliably and future-proofed. </p>
<a className="btn" href="#">Learn more about our ethos</a>
</div>
</Col>
<Col sm={12} md={6}>
<div className="position-relative">
<CapsuleSvg image="images/2-young-men-looking-at-a-desktop-computer-in-an-office.jpg" setter="false" toggle={onToggle}/>
<LineSvg/>
</div>
</Col>
</Row>
</Container>
</section>
</Layout>
)
}
export default HomePage;
Solution 1:[1]
I would do something like adding a prop which would look like this..
Small change in your LineSvg
const LineSvg = ({redLineActive}) => {
return(
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 59.6 830" xmlSpace="preserve" className="capsules capsules-image-bottom-right position-absolute">
{redLineActive ?
<path id="red-line" className="capsule-a capsule-foreground fill-red track-on-scroll" d="M10.4,257.6A10.39,10.39,0,0,1,20.8,268V584.4a10.4,10.4,0,0,1-20.8,0V267.9A10.37,10.37,0,0,1,10.4,257.6Z" />
: null }
<g className="track-on-scroll">
<path id="green-line" d="M49.2,394.7a10.39,10.39,0,0,1,10.4,10.4v84.4a10.4,10.4,0,0,1-20.8,0V405.1A10.33,10.33,0,0,1,49.2,394.7Z" className="capsule-b fill-green" />
<path id="blue-line" d="M49.2,354.6A10.39,10.39,0,0,1,59.6,365v4.9a10.4,10.4,0,1,1-20.8,0v-5A10.31,10.31,0,0,1,49.2,354.6Z" className="capsule-c fill-blue" />
<path id="grey-line" d="M49.2,235.2a10.39,10.39,0,0,1,10.4,10.4V330a10.4,10.4,0,0,1-20.8,0V245.6a10.33,10.33,0,0,1,10.4-10.4Z" className="capsule-d fill-grey-light" />
</g>
</svg>
)
}
export default LineSvg;
Then in your index you could do something like this. Im not sure how you plan on toggling it so adjust to how you plan to toggle it.
...
const [redToggle, setRedToggle] = useState(true);
...
return (
...
<LineSvg redLineActive={redToggle}/>
<button onClick={() => setRedToggle(!redToggle}>Toggle</button>
...
There are some other ways to do it if you want multiple red line svg's but let me know.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Matt |
