Reputation: 1671
I want to reproduce the effect I coded in this vanilla JS example in my React app.
This is my Sass
.item
opacity: 0
transition-property: opacity
transition-timing-function: ease-in
.is-transitioning
opacity: 1
the loop generating the images and their containers:
this.props.images.map((image, index) => <ImageContainer key={`img-${index}`}
image={image}
transitionDuration={Math.trunc(index * Math.random() * 1000) + 200} />
)
and finally the ImageContainer component:
const ImageContainer = (props) => (
<div className="item is-transitioning"
style={{ transitionDuration: `${props.transitionDuration}ms` }}
>
<img src={`${props.image.path}`} />
</div>
);
export default ImageContainer;
Even though the inline class is correctly applied and the css is there, I can't figure out why the effect doesn't show up.
Upvotes: 3
Views: 157
Reputation: 726
(As said in another answer to this thread,) The issue is that the CSS (classes) didn't change, so the transition is "not needed", causing no animation.
For React people who wants to use transition over animation or other libraries, here is a "working" fiddle with a dirty hack: https://jsfiddle.net/s16nd2j5/
The trick is to add the class to <ImageContainer>
in componentDidMount()
with a setTimeout
for 0ms.
setTimeout( _ => this.setState({ transitioning: true }), 0);
This kinda forces the state update to be "postponed" to another render, causing the "CSS class change" to take place.
P.S. it is a hack. The code smells when a setTimeout / setInterval
is used like this.
P.P.S. The shuffle()
part from OP's fiddle is omitted for simplicity.
Upvotes: 0
Reputation: 273970
The issue is that the is-transitioning
is added from the beginning so your elements are already at opacity:1
and notihng will happen. You need to add the class in order to trigger the opacity change and see the transition.
Another way, in case you cannot add the class is to use animaton. Here is the JS example that you can convert to react:
Array.from(document.querySelectorAll('.item')).map((i, index) => {
i.style.animationDuration = `${(index * Math.trunc(Math.random() * 1000)) + 200}ms`;
});
.container {
display: flex;
}
.item {
display: flex;
justify-content:center;
align-items: center;
width: 1rem;
height: 1rem;
background-color: teal;
padding: 2rem;
margin-right: 1.2rem;
border-radius: 10px;
font-size: 2rem;
color: white;
opacity: 0;
animation:change 2s forwards;
}
@keyframes change{
to {
opacity:1;
}
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
Simply keep the same code you wrote and replace transitionDuration
with animationDuration
and adjust the CSS.
Upvotes: 1