3

I've got 2 components that are conditionally shown or hidden based on a string value stored in useState as showModal

{showModal === 'SIGNIN' && <SignIn />}
{showModal === 'JOIN' && <Join />}

I want to fade in one component, then when the state changes, fade it out and fade in the other component.

Can this be done with react transition group?

I tried

<TransitionGroup>
    <CSSTransition in={showModal === 'SIGNIN' ? true : false} classNames='fade' timeout={220} key={showModal}>
       <div> 
          <SignIn />
       </div>
     </CSSTransition>
     <CSSTransition in={showModal === 'JOIN' ? true : false} classNames='fade' timeout={220} key={showModal}>
       <div> 
         <Join />
       </div>
     </CSSTransition>
</TransitionGroup>

I don't get any error, one component is shown, changing showModal from 'SIGNIN' to 'JOIN' does nothing. Inspecting the divs with the timeout set to 22000 shows that no new classes have been added.

Bill
  • 4,614
  • 13
  • 77
  • 132
  • You may need to wrap each inner component in its own `CSSTransition` component. I'm new to them myself, though. – isherwood Sep 27 '21 at 20:25
  • Looks like that's the case: http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-prop-children – isherwood Sep 27 '21 at 20:26
  • yes this example maps over an array and then animates items going in and out of the array, I don't have an array, I just got 2 components – Bill Sep 27 '21 at 20:28
  • I wonder if that error isn't just a long-winded way of telling you you're missing [props](http://reactcommunity.org/react-transition-group/css-transition) on `CSSTransition`. In my one implementation I used the state value in an `in` property. What are you doing for that? – isherwood Sep 27 '21 at 20:42
  • thanks again, I've updated the question to show the attempt at using the `in` – Bill Sep 27 '21 at 20:47

1 Answers1

1

SwitchTransition from react transition group might help.

Example

const { useState, useEffect } = React;
const { SwitchTransition, CSSTransition } = ReactTransitionGroup;

const SignIn = () => <div className="block sign-in">Sign In</div>;

const Join = () => <div className="block join">Join</div>;

const App = () => {
const [showModal, setModal] = useState("SIGNIN");

  useEffect(() => {
      let handle;
      
      const loop = () => {
      
        setModal(state => state === "JOIN" ? "SIGNIN" : "JOIN");
      
        handle = setTimeout(loop, 2500);
      };
  
      handle = setTimeout(loop, 1000);
      
      return () => {
        clearTimeout(handle);
      }
  }, []);
  
  const addEndListener = (node, done) => {
              node.addEventListener("transitionend", done, false);
            }

return <div>
  <SwitchTransition mode="out-in">
    <CSSTransition
      key={showModal === "SIGNIN"}
      addEndListener={addEndListener}
      classNames="fade">
        {showModal === "SIGNIN" ? <SignIn/> : <Join/>}
  </CSSTransition>
</SwitchTransition>
</div>;
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
  );
body {
  margin: 0;
  overflow: hidden;
  font-family: Georgia, serif;
}

.block {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 10px;
  color: white;
  width: 200px;
  height: 100px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 30px;
}

.sign-in { 
  background: #0984e3;
}

.join {
  background: #6c5ce7;
}

.fade-enter {
   opacity: 0;
    transform: translate(-100%, -50%);
}

.fade-exit {
   opacity: 1;
   transform: translate(-50%, -50%);
}

.fade-enter-active {
   opacity: 1;
   transform: translate(-50%, -50%);
}

.fade-exit-active {
   opacity: 0;
   transform: translate(100%, -50%);
}

.fade-enter-active,
.fade-exit-active {
   transition: opacity 500ms, transform 500ms;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-transition-group@4.4.2
/dist/react-transition-group.min.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>
Józef Podlecki
  • 10,453
  • 5
  • 24
  • 50
  • 1
    thank you for this great looking answer, ill be checking it out this evening for sure! Thanks again! – Bill Sep 30 '21 at 09:58