1

I've come up with the following code using React Transition Group:

const Transition = ({ elements, selectKey, render: Element, ...props }) => (
  <TransitionGroup {...props}>
    {elements.map((element) => (
      <CSSTransition
        key={selectKey(element)}
        timeout={1000}
        className="transition-slide"
      >
        <Element {...element} />
      </CSSTransition>
    ))}
  </TransitionGroup>
)

The key part here is that Transition component receives the render prop and renders it applying some transitions.

The way I expected for this to work:

<Transition render={(props) => <Toast {...props} />} />

But this code does not work as I expected: the transition of the next element interrupts the transition of the previous one.

However, this code works just fine:

const Element = (props) => <Toast {...props} />

// ...

<Transition render={Element} />

How can I fix this issue without putting the desired render-prop into a separate component?

Codesandbox: Example sandbox. The sandbox presents a non-working option with animation interruption. To get a working version, you need to uncomment lines 16 and 30 in the /Toasts/index.js file

P.S. I can't just use render={Toast} because I need to do ({id}) => <Toast dismiss={() => {deleteToast(id)}} />. I omitted this detail in order to simplify the understanding of the problem.

satma0745
  • 667
  • 1
  • 7
  • 26

1 Answers1

1

If you don't want to put the render function into another component, putting it into a useCallback() solved it for me.

const Toasts = () => {
  const [toasts, addToast] = useToasts();

  const Element = useCallback((props) => <Toast {...props} />, []);

  return (
    <div>
      <button onClick={addToast}>Add toast</button>

      <List>
        <Transition
          elements={toasts}
          selectKey={({ id }) => id}
          render={Element}
        />
      </List>
    </div>
  );
}

(I don't quite understand the origin of the issue, but it has to do something with the function references.)

Henya14
  • 86
  • 3
  • 1
    I also decided to use the `useCallback` hook, but it seems quite odd. Even docs are saying that hooks like `useCallback` and `useMemo` are meant to be used only for optimization purposes and cannot guarantee consistent behavior in such cases – satma0745 Aug 05 '21 at 18:55
  • Yes, I found it odd too, this was meant to be a quick fix, but I'll look deeper into the docs, because I really want to know what causes this behaviour :D – Henya14 Aug 06 '21 at 03:44