1
votes

I have two boxes stack on each other in a vertical position, and I have a button in the middle, I want to click on the button, the upper box moves up and the bottom one moves down, after I click the button, they move back.

I use the useState hook to set the Boolean number and attach it to the OnClick event handleClick function. Now when you click the button, you can switch true and false. I want to use that to toggle on and off the props which I send to my styled component. Is that possible?

I only figure out useRef hook could help me get the DOM element, So when I click on the button, I can get the styled component element, but I don't know how to access the props I sent to my styled component, And also attach it to my Boolean.

import React,{ useRef, useState} from "react";
import styled,{css, keyframes} from "styled-components";

const SkillCardContainer = styled.div`
        position:relative;
        width:300px;
        height:450px;
        background:blue;
        margin:200px auto;
    `;

    const moveUp = keyframes`
       from{ top: 0;}
       to{ top: -50%}
    `;
    const moveDown = keyframes`
        from { top: 50;}
        to {top: 100%;}
    `;

    const UpPart = styled.div`
        position:absolute;
        width:300px;
        height:225px;
        background:red;
        box-sizing:border-box;
        top:0
        left:0;
        z-index:80;
        ${props => props.showUp ? css`animation: ${moveUp} 1s linear;`:css`animation:none` };
    `;
    const DownPart = styled.div`
        position:absolute;
        width:300px;
        height:225px;
        background:green;
        box-sizing:border-box;
        top:50%;
        left:0;
        z-index:80;
        ${props => props.showDown ? css`animation:${moveDown} 1s linear;`:css`animation:none`};
    `;
     
    const Button = styled.button`
        width:100px;
        height:50px;
        box-sizing:border-box;
        background:grey;
        position:absolute;
        top:50%;
        left:50%;
        transform: translate(-50%, -50%);
        z-index:100;
    
    `;



    const SkillCard = () => {
        
        const myRef = useRef(null);
        const [isClick, setIsClick] = useState(false);

        const handleClick = () =>{
            setIsClick(!isClick);
        };
        
    return (  
            <React.Fragment>
                <SkillCardContainer>
                        <UpPart showUp ref={myRef} ></UpPart>
                           <Button onClick={handleClick}>HTML</Button>
                        <DownPart showDown></DownPart>
                </SkillCardContainer>
            </React.Fragment>
        );
    }
    export default SkillCard;
2
useRef is not a good solution for this... just create a const with a conditional that defines which style you need when the boolean is true and when it is falseJonathan Alfaro
even better use an actual store like redux and a reducerJonathan Alfaro

2 Answers

1
votes

You don't need a ref. You need to be passing props to UpPart and DownPart which change based on your state.

Your styled.divs are expecting props.showUp and props.showDown to be sometimes true and sometimes false. So pass them the isClick boolean.

<UpPart showUp={isClick} ></UpPart>
   <Button onClick={handleClick}>HTML</Button>
<DownPart showDown={isClick}></DownPart>

The above change causes the animation to run when the button is clicked. But the styles need more work because it snaps back to the original position when the animation is done.

0
votes

You can assign properties to your styled component and access them like this:

interface Props {
  ...myProps
}
const StyledComponent= styled.div<Props>`
 display: ${(props) => props.myProp ? 'block' : 'inline-block';
`

or more simple like:

const StyledComponent= styled.div<{ myProp: boolean }>`
 display: ${(props) => props.myProp ? 'block' : 'inline-block';
`