petyosi / react-virtuoso

The most powerful virtual list component for React
https://virtuoso.dev
MIT License
5.25k stars 301 forks source link

Unable to integrate with React transition group #217

Closed qweluke closed 3 years ago

qweluke commented 3 years ago

When trying to wrap Virtuoso with TransitionGroup I'm getting this error

Failed to execute 'observe' on 'ResizeObserver': parameter 1 is not of type 'Element'.

codesandbox: https://codesandbox.io/s/intelligent-dubinsky-cowpj

import React, { useState, useCallback } from "react";
import { Button, Card, Box, Typography } from "@material-ui/core";
import { Virtuoso } from "react-virtuoso";
import { CSSTransition, TransitionGroup } from "react-transition-group"; // ES6
import "./animations.css";

const MyComponent = ({ history }) => {
  const [allRescues, setAllRescues] = useState([
    { id: 1, name: 123 },
    { id: 2, name: "name 2" },
    { id: 3, name: "name 2" },
    { id: 4, name: "name 2" },
    { id: 5, name: "name 2" },
    { id: 6, name: "name 2" }
  ]);

  // computeItemKey is necessary for animation to ensure Virtuoso reuses the same elements
  const computeItemKey = useCallback(
    (index) => {
      return allRescues[index].id;
    },
    [allRescues]
  );

  const ListContainer = ({ listRef, children, className, style }) => {
    return (
      <TransitionGroup
        ref={listRef}
        className={className}
        style={{
          ...style,
          height: "100%",
          marginBottom: 0,
          backgroundColor: "pink"
        }}
      >
        {children}
      </TransitionGroup>
    );
  };

  const removeRescue = (rescue) =>
    setAllRescues(allRescues.filter((r) => r.id !== rescue.id));

  return (
    <Virtuoso
      style={{ width: "100%", height: "400px", backgroundColor: "pink" }}
      totalCount={allRescues.length}
      computeItemKey={computeItemKey}
      ListContainer={ListContainer}
      item={(index) => {
        const rescue = allRescues[index];
        return (
          <CSSTransition
            key={rescue.id}
            timeout={{
              exit: 700,
              enter: 400
            }}
            classNames="item"
          >
            <Box css={{ backgroundColor: "blue" }}>
              <Typography variant="h3">{rescue.name}</Typography>
              <Button onClick={() => removeRescue(rescue)}>DELETE</Button>
            </Box>
          </CSSTransition>
        );
      }}
    />
  );
};

export default MyComponent;
petyosi commented 3 years ago

@qweluke I am not familiar with TransitionGroup, but from what I see, it looks like the listRef does not get assigned the actual DOM element - and it needs to get there in order for the size tracking to work.