React-transition-group: CSSTransition children don't actually leave DOM when 'in' prop is false. It just plays the exit animation

Created on 23 Jan 2018  路  4Comments  路  Source: reactjs/react-transition-group

Do you want to request a feature or report a bug?
Report bug.

What is the current behavior?
When props.in is falsey, the -exit animation is played, but children of CSSTransition aren't actually removed from the DOM or hidden.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar (template: https://jsfiddle.net/m4mb9Lg3/4/).
The bug is apparent in the codebox in the docs (https://codesandbox.io/s/yv645oq21x?from-embed) and in this one found elsewhere in this repo's issues: https://codesandbox.io/s/ymypv01939.

In the latter example, when state.show is set to false, the box "disappears" (opacity played from 1 to 0.01 over 800ms), but then reappears immediately until state.show is set back to true, at which point it plays the -enter animation.

What is the expected behavior?
I'd expect the children to not be present in the DOM when in is falsey.

Which versions, and which browser / OS are affected by this issue? Did this work in previous versions?
This worked in react-addons-css-transition-group, which we could use up until React 16.

Basically, neither of these patterns work:

1)

<CSSTransition in={!minimized} timeout={500} classNames="widgetBody">
  {children}
</CSSTransition>

In this case, I'm expecting the library to handle existence of the children, but unlike what the docs seem to expect, this doesn't happen and the library just plays the -exit animation when in is toggled.

2)

<CSSTransition in={!minimized} timeout={500} classNames="className">
  {!minimized ? children : <div style={{ display: 'none' }} />}
</CSSTransition>

In this case, I'm handling existence of the children (which seems redundant since it's the same variable as in), but since <CSSTransition> needs a child (can't be null even though React can handle that?), I'm feeding it an empty div, which apparently cancels out the -exit animation, which does not play.

Most helpful comment

yes it doesn't remove the element unless you set unmountOnExit

All 4 comments

yes it doesn't remove the element unless you set unmountOnExit

Ah gotcha, thank you. For anyone expecting CSSTransition to behave a bit more like the old versions, I'm basically using this everywhere:

const Transition = ({ inVar, children, ...oldProps }) => {
  const props = { unmountOnExit: true, ...oldProps, in: !!inVar };
  return (
    <CSSTransition {...props}>
      <React.Fragment>{children}</React.Fragment>
    </CSSTransition>
  );
};

Which is CSSTransition but it:
1) handles multiple children
2) uses regular js truthy/falsey instead of mandatory boolean
3) unmounts on exit as expected

Cheers!

Also, don't know who's in charge of it, but I'd propose the unmountOnExit prop is added to the codepen in the docs, as the example given seems to expect that behavior.

handles multiple children

you may want TransitionGroup

Was this page helpful?
0 / 5 - 0 ratings

Related issues

carly1987 picture carly1987  路  3Comments

Kylian030903 picture Kylian030903  路  3Comments

mosesoak picture mosesoak  路  7Comments

r-tock picture r-tock  路  5Comments

mosesoak picture mosesoak  路  5Comments