I have a functional component called ServiceButton, which is placed in a parent functional component called ServiceScreen.
I defined an on-click function (see below function ChangeText() from ServiceButton), in which I want the currently selected service button to increase its margin-bottom (from -19px to 0px) and the newly-clicked ServiceButton to decrease its margin-bottom (from 0px to -19px), during an animation called with setInterval() and defined within the frame() function. The margins are being changed accordingly, but when calling clearInterval and ending the animations, the ServiceButtons return to their before style.
The following is the parent component (ServiceScreen)
function ServiceScreen(props : {
name : string;
thisRef : RefObject<HTMLDivElement>;
}) {
const btnRefs = [useRef<HTMLDivElement>(null),useRef<HTMLDivElement>(null),useRef<HTMLDivElement>(null)];
const textDivRef = useRef<HTMLDivElement>(null);
const [currentIndex, setCurrentIndex] = useState(0);
const [isPlayingAnim, setIsPlayingAnim] = useState(false);
const animDuration = 5;
const frameRate = 120;
return (<div ref={props.thisRef} title={props.name} className={gC([styles.section, styles.serviceSection])}>
<div className={gC([styles.detailDiv,styles.detailDiv1])}></div>
<div className={styles.contentDiv}>
<ServiceButton name="S1" targetIndex={1}></ServiceButton>
<ServiceButton name="S2" targetIndex={2}></ServiceButton>
<ServiceButton name="S3" targetIndex={3}></ServiceButton>
<div ref={textDivRef} className={styles.serviceDiv}>
<p>Servicii</p>
</div>
</div>
<div className={gC([styles.detailDiv,styles.detailDiv2])}></div>
</div>
)
The following is the child component (ServiceButton)
function ServiceButton(props : {
name: string;
targetIndex: number;
})
{
const [currentStyle, setCurrentStyle] = useState(false)
function ChangeText() {
console.log(currentStyle)
var btnCrntMargin = 0;
function frame() {
if(btnCrntMargin == 19)
{
console.log("Done anim")
console.log(btnRefs);
setIsPlayingAnim(false);
setCurrentStyle(true)
setCurrentIndex(props.targetIndex);
console.log(props.targetIndex)
clearInterval(AnimId)
textDivRef.current!.innerHTML = "<p>" + content.servicePage.text[props.targetIndex-1] + "</p>"
}
else
{
btnCrntMargin = btnCrntMargin + 1;
if(currentIndex) btnRefs[currentIndex-1].current!.style.marginBottom = String(-19+btnCrntMargin) + "px";
btnRefs[props.targetIndex-1].current!.style.marginBottom = String(-btnCrntMargin) + "px";
}
}
if(!isPlayingAnim && props.targetIndex != currentIndex) {
setIsPlayingAnim(true);
var AnimId = setInterval(frame,1000*animDuration/frameRate);
}
}
return <div ref={btnRefs[props.targetIndex-1]} onClick={ChangeText} className={(currentStyle) ? gC([styles.serviceButton, styles.selected]) : styles.serviceButton}>
<a className={styles.unselectable}>{props.name}</a>
</div>
}
In the react documentation (here to be more exact), I see the recommended way to propagate a change in style is using States. In the code above, I tried doing this, but the elements still reset to their normal CSS style. I will also provide the styles associated with the ServiceButtons:
.serviceSection .contentDiv .serviceButton {
grid-row: 1;
background-color: rgba(var(--marginal_color),0.9);
border-width: 1em;
border-bottom-width: 20px;
border-style: ridge;
border-radius: 1rem 1rem 0 0;
border-color: rgba(var(--main_color),1);
border-bottom: none;
z-index: 2;
align-content: center;
text-align: center;
transition: background 0.25s;
}
.serviceSection .contentDiv .serviceButton a {
font-size: 4vw;
color: rgba(var(--white_color),1);
text-shadow: 1px 1px rgba(var(--white_color),0.25);
transition: color 0.25s;
}
.serviceSection .contentDiv .serviceButton:hover {
background-color: rgba(var(--main_color),1);
}
.serviceSection .contentDiv .serviceButton:hover a {
color: rgba(var(--marginal_color),1);
text-shadow: 1px 1px rgba(var(--marginal_color),1);
}
.serviceSection .contentDiv .serviceButton:active {
background-color: rgba(var(--dark_main_color),1);
}
.serviceSection .contentDiv .serviceButton:active a {
color: rgba(var(--white_color),1);
text-shadow: 1px 1px rgba(var(--white_color),0.25);
}