React-grid-layout: Don't animate on initial render

Created on 21 Sep 2015  路  9Comments  路  Source: STRML/react-grid-layout

Is it possible to only animate after the initial first render?

So you'd get a static page and it'd only start animating when you drag any of the boxes.

Most helpful comment

This isn't so simple to do given React's model. The elements are all technically rendered at the top left of the container and are translate()d over to their final positions. The only solution I can think of so far is to toggle a state flag on every render past the initial one, to use that class for animations.

Given how hacky that feels, I would rather that the few consumers who really need that functionality implement it in their own applications. Simply set a mounted flag on componentDidMount() on the parent component, use that to set an animated class on the RGL container, then use the following CSS:

.react-grid-item.cssTransforms {
  transition-property: none;
}
.animated .react-grid-item.cssTransforms {
  transition-property: transform;
}

All 9 comments

Do you mean setting
useCSSTransforms={false}
on initial render and true on update?

When you open a view everything animates from 0,0.

It'd feel faster if they had no transition, and once they were in their starting point then enable transitions.

I removed the transitions in the CSS and this was sorted.

I would like to see this re-opened. Having a boolean to turn off the initial animation (completely) on initial page render would be very useful IMO. Besides that:

  • removing css feels like a hack
  • the useCSSTransforms is used for changing animation technique used (not turning animation off)

This isn't so simple to do given React's model. The elements are all technically rendered at the top left of the container and are translate()d over to their final positions. The only solution I can think of so far is to toggle a state flag on every render past the initial one, to use that class for animations.

Given how hacky that feels, I would rather that the few consumers who really need that functionality implement it in their own applications. Simply set a mounted flag on componentDidMount() on the parent component, use that to set an animated class on the RGL container, then use the following CSS:

.react-grid-item.cssTransforms {
  transition-property: none;
}
.animated .react-grid-item.cssTransforms {
  transition-property: transform;
}

Thanks for the quick and thorough reply mr @STRML, I will give this a go.

I appreciated the solution to this, thanks @STRML. Since I don't use componentDidMount, I quickly wanted to share how this is achievable using a functional react component.

import React, { useState, useEffect } from 'react';
import GridLayout from 'react-grid-layout';

const Grid = ({ onLayoutChange, elements }) => {
  const [classNames, setClassNames] = useState(
    'flex layout bg-white shadow rounded-sm'
  );

  useEffect(() => {
    setClassNames('flex layout bg-white shadow rounded-sm animated');
  }, []);

  return (
    <GridLayout
      autoSize
      className={classNames}
      cols={20}
      rowHeight={32}
      width={700}
      margin={[0, 0]}
      compactType={null}
      containerPadding={[0, 0]}
      onLayoutChange={onLayoutChange}
    >
      {elements}
    </GridLayout>
  );
}

Edit:
Beware that this behavior will make the <GridLayout> render twice

@linus-amg I tried the useEffect solution, but was still getting the animation. I ended up setting the state variable in a timeout callback, and now it works perfect.

useEffect(() => {
  const timer = setTimeout(() => setClassNames('layout animated') , 1)
  return () => clearTimeout(timer)
}, [])

I also tried to get rid of the second render, with the help of the useRef hook to mimick @torkelo @alexanderzobnin PR in Grafana, where a member variable is used instead of state. It kinda worked, the first animation was not playing. But, sometimes, after first load, when moving the panels the smooth CSS animation was not applied back. If the component is rendered again, it works fine, as the new class names are now applied. With some debug logs, I figured that on certain occasions, my component was getting rendered twice on first load, and other times only once.

Setting measureBeforeMount={true} solves this problem for me. :)

Was this page helpful?
0 / 5 - 0 ratings