Hi, there should be some way how to animate List component using popular react-transition-group
(https://github.com/reactjs/react-transition-group). Can you try to create example for that?
Sorry @Dharmoslap. I haven't used react-transition-group. Perhaps you (or someone else who has used it) could create such an example and I would be happy to add it to the documentation.
I'd like to, but I'm not sure how to integrate it with react-virtualized.
+1 I'd like to see how react-motion can be used with react-virtualized lists. One idea would be wrapping the row-renderer within a
@Dharmoslap @kumarharsh i spent all day hacking it together but I got it working with the Motion component. The position absolute requirement for the List children container is the real deal breaker as you can't animate just one element and have all the elements below in the list move using position relative (unless i'm mistaken).
In the example when I click, i force update to the new height of the clicked element, and animate the marginTop style of all containers indexes after it. The marginTop defaultStyles on the Motion components are the negative value of my clicked elements new height. I then just spring(0).
I'm going to explore a different option tomorrow by creating a temporary container that wraps around X amount of List children, and is only there for the duration of the animation.

Burned way too much time trying to get it to be smooth. The reality is react motion isn't good for animating elements with a lot of nested children, even if you're only interpolating one div. While it is possible to use react-motion for animating list, if your target users are going to be running older hardware, this just isn't a viable solution. The real lag comes when you interrupt the animation.

@jwdinker nice work. I agree that react-motion isn't good for nested children as it causes the top element to render on every update due to style change passed via props. Though some optimizations can be done using libraries such as immutable.js and shouldComponentUpdate to not render children every millisecond or so...
Can you share the code for the animation above, I'd like to see how you did it.
@jwdinker would love to see a gist for that. Do you happen to have it?
I'm working in a similar hack but it feels too dirty to me. Absolute positioning is really a problem with this kind of animations.
@aitrusgit it's a big mess because I was trying so many different things so you are a welcome to comb through it. I gave it up after 3 weeks of trying because it would get too choppy with a lot of items, and also using the overlay just for animating seemed like a stupid slight of hand trick. You are better off making your own simplified virtualized list using position relative if you are dead set on react-motion. Alternatively, if you are just looking for slick animations with react-motion without the computational overhead of react-motion, I would definitely check out css-spring.
https://gist.github.com/jwdinker/8dd31bf0f2f9b34bd5f2a4c60c1ba2de
James Long shared a video a while back about adding animation to a react-virtualized List. It was kind of a live-coding demo thing. He seemed to have pretty good success with it, though I can't seem to dig up the link now. :(
i think this is the live coding demo from James, animation around 1:10:42
https://www.youtube.com/watch?time_continue=3689&v=a7EGJrwI27Y
Sorry put this comment here in an old topic but maybe can help someone else.
I were able to create an animation in a Table using the following code following the James approach,
took me a while to understand this approach, the main function is RowHof:
import React from 'react';
import {
defaultCellRangeRenderer,
defaultTableRowRenderer,
Table,
type CellRangeRendererParams,
type CellRangeRenderer,
Grid,
SortDirection,
} from 'react-virtualized';
import { sortBy } from 'lodash';
import ColoredScrollbars from './ColoredScrollbars';
type TargetType = { target: { scrollTop: number, scrollLeft: number } };
type PropsType = {
data: Array<Object>,
defaultColumn: string,
sortMethod: (Array<Object>, column: string) => Array<Object>,
rowClassName: Function,
};
type StateType = {
column: string,
direction: SortDirection.ASC | SortDirection.DESC,
};
class ScrollableTable extends React.Component<PropsType, StateType> {
static headerIndex = -1;
static defaultProps = {
sortMethod: (results: Array<Object>, column: string) =>
sortBy(
results,
row =>
typeof row[column] === 'string'
? row[column].toLowerCase()
: row[column]
),
};
constructor(props: PropsType) {
super(props);
this.state = {
column: props.defaultColumn,
direction: SortDirection.ASC,
};
}
table: ?{ Grid: Grid };
handleScroll = ({ target: { scrollTop, scrollLeft } }: TargetType) =>
this.table && this.table.Grid.handleScrollEvent({ scrollTop, scrollLeft });
handleSort = (sorting: { sortBy: string }) => {
const { column, direction } = this.state;
const clickedColumn = sorting.sortBy;
if (column !== clickedColumn) {
this.setState({
column: clickedColumn,
direction:
direction === SortDirection.ASC
? SortDirection.DESC
: SortDirection.ASC,
});
return;
}
this.setState({
direction:
direction === SortDirection.ASC
? SortDirection.DESC
: SortDirection.ASC,
});
};
cellRangeRenderer = (tableProps: Table.propTypes): CellRangeRenderer => (
props: CellRangeRendererParams
) => {
if (this.props.data.length === 0) {
return [{ ...tableProps.noRowsRenderer(), key: 'no-results' }];
}
return [
<ColoredScrollbars
style={{
height: tableProps.height - tableProps.headerHeight,
}}
onScroll={this.handleScroll}
key="scrollbar"
>
<div style={{ height: this.props.data.length * tableProps.rowHeight }}>
{defaultCellRangeRenderer(props)}
</div>
</ColoredScrollbars>,
];
};
RowHof = (rowRendererFn: defaultTableRowRenderer) => {
function tableRowFn(props: CellRangeRendererParams) {
const propsStyled = {
...props,
style: {
...props.style,
top: 0,
transform: `translate3d(0px,${props.style.top}px, 0px)`,
willChange: 'transform',
transition: '1s transform',
},
};
const row = rowRendererFn({
...propsStyled,
});
const rowWithId = { ...row, key: props.rowData.id || props.key };
return rowWithId;
}
return tableRowFn;
};
RowRenderer = this.RowHof(defaultTableRowRenderer);
render() {
const { props } = this;
const { column, direction } = this.state;
const results = props.sortMethod(props.data || [], column);
if (this.state.direction === SortDirection.DESC) {
results.reverse();
}
return (
<Table
ref={instance => {
this.table = instance;
}}
sort={this.handleSort}
sortBy={column}
sortDirection={direction}
cellRangeRenderer={this.cellRangeRenderer(props)}
rowRenderer={this.RowRenderer}
rowCount={results.length}
rowGetter={({ index }) => results[index]}
{...props}
rowClassName={({ index }) => {
if (index === ScrollableTable.headerIndex) return '';
return this.props.rowClassName(results[index]);
}}
/>
);
}
}
export default ScrollableTable;
@hernanif1 If you're using the defaultTableRowRenderer and you want to specify a key and alter the style, I think you can do somthing a bit simpler and more generic:
const makeRowRenderer: (
keyField: string
) => TableRowRenderer = keyField => rowProps =>
defaultTableRowRenderer({
...rowProps,
key: rowProps.rowData[keyField] || rowProps.key,
style: {
...rowProps.style,
top: 0,
transform: `translate3d(0px,${rowProps.style.top}px, 0px)`,
willChange: "transform",
transition: "300ms transform"
}
});
const rowRenderer = makeRowRenderer("id");
Sorry for ping on this closed issue...
@jwdinker I do love to see the gist to understand how did you achieve that smooth animation that you showed in the gif, the current link in broken. I am breaking my head for weeks on this.
Sorry for ping on this closed issue...
@jwdinker I do love to see the gist to understand how did you achieve that smooth animation that you showed in the gif, the current link in broken. I am breaking my head for weeks on this.
@assuncaocharles I feel your pain. I might be able to provide some input if you fill me in on what kind of animation you want to achieve. It's been years since I messed with react-virtualized and I use my own virtualization lib now, but I remember the headaches and limitations pretty well. I think if you can migrate to react-window that might make things easier because it's less complex.
Sorry for ping on this closed issue...
@jwdinker I do love to see the gist to understand how did you achieve that smooth animation that you showed in the gif, the current link in broken. I am breaking my head for weeks on this.@assuncaocharles I feel your pain. I might be able to provide some input if you fill me in on what kind of animation you want to achieve. It's been years since I messed with react-virtualized and I use my own virtualization lib now, but I remember the headaches and limitations pretty well. I think if you can migrate to react-window that might make things easier because it's less complex.
Thanks for the reply @jwdinker the Animation I am aiming to create is very similar to the give you posted in the give where you expand nested list... The best I could achieve was this: https://codesandbox.io/s/02xbc
Sorry for ping on this closed issue...
@jwdinker I do love to see the gist to understand how did you achieve that smooth animation that you showed in the gif, the current link in broken. I am breaking my head for weeks on this.
@assuncaocharles I feel your pain. I might be able to provide some input if you fill me in on what kind of animation you want to achieve. It's been years since I messed with react-virtualized and I use my own virtualization lib now, but I remember the headaches and limitations pretty well. I think if you can migrate to react-window that might make things easier because it's less complex.
Thanks for the reply @jwdinker the Animation I am aiming to create is very similar to the give you posted in the give where you expand nested list... The best I could achieve was this: https://codesandbox.io/s/02xbc
@assuncaocharles i'll dive in more tomorrow but my initial thoughts are you don't want to use a fixed size list. You'll want to use:
The real issues with the animations is overlap with mount/unmount during a quick scroll. If I remember correctly, I think I used some slight of hand tricks to animate temporary clones of the elements to get around this. React virtualized / react window instantly unmounts components once they are outside the visible index range because of the size of the nested children.
Most helpful comment
Burned way too much time trying to get it to be smooth. The reality is react motion isn't good for animating elements with a lot of nested children, even if you're only interpolating one div. While it is possible to use react-motion for animating list, if your target users are going to be running older hardware, this just isn't a viable solution. The real lag comes when you interrupt the animation.