Home > front end >  React - Can I apply css effect on the first render only?
React - Can I apply css effect on the first render only?

Time:10-30

I have a simple React component that displays some text with a 'typewriter' kind of effect via CSS. The problem I have is that this typewriter effect is re-displayed every time the component re-renders but I only want it applied on the first render and never again. Is there a way to achieve this? Below is an example...

import React from 'react';
import './Typewriter.css'

export function Blah() {
    return <div className='typewriter'>
        My typewriter text here
    </div>
}
.typewriter {
    font-family: monospace;
    color:#0000;
    background:
            linear-gradient(-90deg, #39ff14 5px,#0000 0) 10px 0,
            linear-gradient(#39ff14 0 0) 0 0;
    background-size:calc(100*1ch) 200%;
    -webkit-background-clip:padding-box,text;
    background-clip:padding-box,text;
    background-repeat:no-repeat;
    animation:
            b .7s infinite steps(1),
            t calc(100*.01s) steps(100) forwards;
}
@keyframes t{
    from {background-size:0 200%}
}
@keyframes b{
    50% {background-position:0 -100%,0 0}
}

CodePudding user response:

Stop the animation after the first time by using useRef and useEffect as in the following example

const { useRef, useEffect } = React;

const Example = () => {
const firstRender = useRef(true);

useEffect(() => {
    firstRender.current = false;
}, []);

return <div className={firstRender.current ? 'typewriter' : ''}>
    My typewriter text here
</div>
    
}
ReactDOM.render(<Example />, document.getElementById("react"));
.typewriter {
    font-family: monospace;
    color:#0000;
    background:
            linear-gradient(-90deg, #39ff14 5px,#0000 0) 10px 0,
            linear-gradient(#39ff14 0 0) 0 0;
    background-size:calc(100*1ch) 200%;
    -webkit-background-clip:padding-box,text;
    background-clip:padding-box,text;
    background-repeat:no-repeat;
    animation:
            b .7s infinite steps(1),
            t calc(100*.01s) steps(100) forwards;
}
@keyframes t{
    from {background-size:0 200%}
}
@keyframes b{
    50% {background-position:0 -100%,0 0}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

CodePudding user response:

I've created a sandbox for your component and I'm not seeing the effect you mentioned: https://codesandbox.io/s/react-playground-forked-w78bd2?file=/Blah.jsx

When you click the button it changes the text which re-renders the component (but does not re-mount it) and that does not cause the animation to happen again.

Perhaps you are re-mounting the component and the problem is further upstream in your app?

  • Related