How to Trigger a CSS Animation on Every Time a React Component Re-Renders

How to trigger a CSS animation on EVERY TIME a react component re-renders

Add a key like this:

function Card({ cardText }) {
return <div key={cardText} className="roll-out">{cardText}<div/>
}

In your code, when the div re-renders, react only changes its inner text. Adding a key will make react think it's a different div when the key changes, so it'll unmount it and mount again.

How to add CSS animation to specific re-rendered item in React?

What you essentially want to do is restart a CSS animation for a particular element. To be honest, I'm not sure of a better way to do this in React than by accessing the DOM element with a reference.

You can do this by making each item its own component and using useRef to get access to the DOM element you want to animate, and then apply the animation code in the linked stack overflow answer above.

const RenderItem = ({ item, handleIncrease }) => {
const stockElem = useRef()

const animate = () => {
let s = stockElem.current
s.style.animation = 'none'
// I had to do "let x =" here because my create-react-app config was yelling at me
let x = s.offsetHeight; // trigger reflow
s.style.animation = null
}

const increase = () => {
handleIncrease()
animate()
}

return (
<div>
<div>{item.fruit}</div>
<div ref={stockElem} className="add-color">{item.stock}</div>
<button onClick={increase}>increase</button>
<br />
<br />
</div>
)
}

And then in your main component, render each item:

return <RenderItem key={item.id} item={item} handleIncrease={handleIncrease} />;

The key approach

There is a way to do this with key, but I don't like it since it goes against key's purpose as defined by React, and can probably lead to problems down the road.

return (
<div key={`${item.id}-${item.stock}`}>
<div>{item.fruit}</div>
<div className="add-color">{item.stock}</div>
<button onClick={handleIncrease}>increase</button>
<br />
<br />
</div>
);

The key line is <div key={`${item.id}-${item.stock}`}>. React will un-mount and remount an element whose key changes. So, this utilizes the uniqueness of item.id combined with the fact that item.stock changes to rerender the div.

Again, even though the first solution I provided is more verbose, it's definitely more canonical.

How to add animations on every re-render of component

Just add something data to <h2>-tag, then React can re-render this tag and animation started.

<h2 className="question" key={currentQuestion}>{questions[currentQuestion]}</h2>

React: Calling Render() during animation. What happens?

On this case CSSTransition is keeping internal state to know in which phase of the animation it is.

React does not reset the state of the CSSTransition instance because it knows it refers to the same element (React relies on the type of component and position on the tree to decide if it is the same element, or on the key prop when defined)

Because the internal state of CSSTransition is the same it's render method renders the same css class before and after the state change on your component.

See your example it working without flicker https://codesandbox.io/s/hopeful-shaw-c9ldr

CSSTransition might change the state in response to a change in any of the props you pass to it (which in this case does not even occur) but that's dependant on the CSSTransition implementation.

Finally, if you passed a different key to CSSTransition it would reset the animation as React would consider it a new component, so would unmount the previous one and mount a new one, with a new internal state.

see the example with the animation reseting here:
https://codesandbox.io/s/jolly-maxwell-2ihkf

re-triggering css animations with react

(Thanks again to @leo for this answer which helped me get to this one!)

I got the desired behavior (forcing the animation to restart) by

  1. Immediately removing the highlight class, and
  2. Setting a timeout (10msec seems to be fine) for adding back the highlight class.

The timeout seems to force react to separately render the component without the highlight class and then again with the highlight class, causing the animation to restart. (Without the timeout, react may collapse these changes into one render step, causing the DOM to treat the whole thing as a no-op.)

A nice result of this approach where each Item manages its own highlight state is that multiple items can be highlighted at the same time (e.g. if updates for one item come in before the highlight fades on another).

Demo here

const Item = ({ id, updateTime }) => {
const [showHighlight, setShowHighlight] = React.useState(false);

// By putting `updateTime` in the dependency array of `useEffect,
// we re-trigger the highlight every time `updateTime` changes.
useEffect(() => {
if (updateTime) {
setShowHighlight(false);
setTimeout(() => {
setShowHighlight(true);
}, 10);
}
}, [updateTime]);

return <div className={showHighlight ? "updated" : ""}>Item {id}</div>;
};

const App = () => {
// tracking the update times at the top level
const [updateTimes, setUpdateTimes] = React.useState({});

// ...
<Item key={id} id={id} updateTime={updateTimes[id]} />

// ...
<button
onClick={() => {
setUpdateTimes({ ...updateTimes, [id]: Date.now() });
}}
>
// ...
}

My animation is not working when re rendering my react component?

You could make use of keys that react is using to determine whether something has changed. This means that your render method should look something like this:

import shortid from "shortid";

getRandomKey = () => {
return shortid.generate();
}

render() {
return (
<div
key={this.getRandomKey()}
className={cs({
"tls-forms": true,
"tls-forms--large": this.props.type === "S",
"tls-forms--medium tls-forms--login": !(this.props.type === "S")
})}
>
// content here
</div>);
}

Since you need to run animation on each render, you'll need to generate some random key every time (that's why we are calling this.getRandomKey() on each render). You can use whatever you like for your getRandomKey implementation, though shortid is pretty good for generating unique keys.

React 17.0.2 Functional Component Only Plays CSS Animation on First Render

During re-render react looks for only the elements which have changed. If not, then it doesn't update the element, even if it rerenders.

So you can either make react know that this element have changed, or unmount and mount the component again. I have provided both the usecases.

  1. You can add a key prop with a random value, so that react knows its different on each re-render and hence remounts the component. This is quick and hacky and it works.
const UserFeedBackComponent = (props) => {
console.log("UserFeedBackComponent rendered");
const rand = Math.random();

return (
<div className={classes.Border} key={rand}>
<div className={classes.CorrectAnswer}>Correct!</div>
</div>
);
};

https://codesandbox.io/s/reactcssanimationissue-forked-9jufd


  1. Another way would be to remove it from the dom after its invisible. The logic will be handled by its parent, InputComponent
import React, { useState } from "react";
import UserFeedBackComponent from "../UserFeedBack/UserFeedBackComponent";
import classes from "./InputComponent.module.css";

const InputComponent = () => {
const [currentInput, setCurrentInput] = useState("");
const [showNotification, setShowNotification] = useState(false);

const inputHandler = (event) => {
setCurrentInput(event.target.value);
setShowNotification(true);
setTimeout(() => {
setShowNotification(false);
}, 3000);
};

return (
<React.Fragment>
<input type="text" value={currentInput} onChange={inputHandler} />
<div className={classes.Output}>{"Output is " + currentInput}</div>
{showNotification && <UserFeedBackComponent text={currentInput} />}
</React.Fragment>
);
};

export default InputComponent;

Every time you need to show the notification, you just need to set showNotification to true, and set it to false again via setTimeout which will fire after the duration of your animation i.e 3s. This is much better because, there's no stale invisible element, polluting your dom. You can still iterate and improve upon it.

https://codesandbox.io/s/reactcssanimationissue-forked-mejre

How to replay a CSS3 animation in Reactjs

ReactJS uses key attribute to distinguish between elements in the diffing algorithm. So, the first time your component loads , react assumes it as new element and renders it accordingly. But next time it tries to render the same element with different data , react feels that it has the same structure and only replaces the new data with old data.

So to apply animations for every change, we need to tell react that this is a new component. This can be done by providing a key to the element with your animation class. And key can be randomly generated using any random number generator( I generally use shortid).

For working example, please refer: this



Related Topics



Leave a reply



Submit