dg2903
dg2903

Reputation: 623

Reactjs and 2 elements animations at once

I am trying to implementing this effect with Reactjs. bellow youtube video is the animation I'm trying to implement :

https://www.youtube.com/watch?v=WVBAMiu1NPE&feature=youtu.be

Now I need to make them into a Reactjs component, I am using react-addons-css-transition-group. what my code should do is everytime I press a button, that will render a div paragraph in the tabContent array, which then should be animated by ReactCSSTransitionGroup. This is my code

constructor(props) {
    super(props);
    this.state = {
      activeTab: 0
    };

    this.active = {
      color: '#4286f4',
      outline: 'none'
    };
    this.inactive = {};
  }


  customChange(tabNum) {
    this.setState({
      activeTab: tabNum
    });
  };

render() {
        var tabContent = [<div>
                          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
                          incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
                          nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
                          </div>,
                          <div>
                          Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
                          eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident
                          </div>,
                          <div>
                          Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
                          doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore
                          veritatis et quasi architecto beatae vitae dicta sunt explicabo.
                          </div>,
                          <div>
                          Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit,
                          sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
                          </div>
                        ]
        return (
            <div className='container-fluid mainDiv'>
                <div id='TabsNav'>
                    <button style={this.state.activeTab === 0 ? this.active : this.inactive} onClick={() => {this.customChange(0)}} className='roundBorderLeft InfoButton'> <br/> btn1 </button>
                    <button style={this.state.activeTab === 1 ? this.active : this.inactive} onClick={() => {this.customChange(1)}} className='adjustLeft InfoButton'> <br/> btn2</button>
                    <button style={this.state.activeTab === 2 ? this.active : this.inactive} onClick={() => {this.customChange(2)}} className='adjustLeft InfoButton'> <br/> btn3</button>
                    <button style={this.state.activeTab === 3 ? this.active : this.inactive} onClick={() => {this.customChange(3)}} className='adjustLeft roundBorderRight InfoButton'>  <br/> btn4</button>
                </div>
                <div id='TabContents'>
                  <ReactCSSTransitionGroup transitionName='tab' transitionEnterTimeout={2000} transitionLeaveTimeout={2000}>
                      {tabContent[this.state.activeTab]}
                  </ReactCSSTransitionGroup>
                </div>
            </div>
        );
      }

this is part of my css i used for transition:

.tab-enter {
  opacity: 0;
  padding-left: 0;
  -webkit-transition: opacity 2s, padding-left 2s;
}

.tab-enter.tab-enter-active {
  opacity: 1;
  padding-left: 100px;
}

.tab-leave {
  opacity: 1;
  padding-left: 100px;
  -webkit-transition: opacity 2s, padding-left 2s;
}

.tab-leave.tab-leave-active {
  opacity: 0;
  padding-left: 200px;
}


.mainDiv {
  padding-top: 100px;
  padding-bottom: 100px;
  color: grey;
  background-color: #fafafa;
  border-bottom: 1px solid #ebebeb;

}

My code shown no animation, the tab's content appears instantly without any animation. what did i do wrong?

Upvotes: 1

Views: 119

Answers (2)

Upasana
Upasana

Reputation: 1975

I checked it locally, you missed only one thing. Your code will work if you assign 'key' to your tabcontent div elements. You must provide the key attribute for all children of ReactCSSTransitionGroup, even when only rendering a single item. This is how React will determine which children have entered, left, or stayed. Check documentation.

var tabContent = [<div key="0">
                          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
                          incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
                          nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
                          </div>,
                          <div key="1">
                          Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
                          eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident
                          </div>,
                          <div key="2">
                          Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
                          doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore
                          veritatis et quasi architecto beatae vitae dicta sunt explicabo.
                          </div>,
                          <div key="3">
                          Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit,
                          sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
                          </div>
                        ]

The css you have provided you will need to modify it for the result you want. Apart from that this 'key' will do the trick.

Upvotes: 1

Ji aSH
Ji aSH

Reputation: 3457

heres a way to achieve what you want :

JS

var Hello = React.createClass({
    getInitialState: function() {
        return {
            activeTab: 0,
            previousTab: -1
        };
    },
    customChange: function (tabNum) {
        this.setState({
            activeTab: tabNum,
            previousTab: this.state.activeTab
        });
    },

    buildButton: function (content, index) {
        return (
            <button 
                key={index}
                className={"button" + (index === this.state.activeTab ? " active" : "")} 
                onClick={() => {this.customChange(index)}}>
                btn{index + 1}
            </button>
        )
    },

    buildContent: function (content, index) {
        let clazz = "item"
        clazz += (index === this.state.activeTab ? " active" : "")
        clazz += (index === this.state.previousTab ? " inactive" : "")
        return (
            <div
                key={index}
                className={clazz}>
                {content}
            </div>
        )
    },

    render: function() {
        var tabContent = [
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
            "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident",
            "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.",
            "Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt."
        ]
        return (
            <div className='container-fluid mainDiv'>
                <div className="buttons">
                    {tabContent.map(this.buildButton)}
                </div>
                <div className='content'>
                    {tabContent.map(this.buildContent)}
                </div>
            </div>
        );
      }
});

ReactDOM.render(
  <Hello name="World" />,
  document.getElementById('container')
);

CSS

.buttons {
  text-align: center;
}

.buttons .button {
  outline: none;
  color: grey;
  margin: 5px;
  border: 0;
  background: 0;
}

.buttons .button.active {
  color: black;
}

.content {
  text-align: center;
  margin-top: 10px;
  position: relative;
}

.item {
  opacity: 0;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}

.item.active {
  animation-name: fade-in;
  animation-duration: 0.6s;
  animation-fill-mode: forwards;
}
.item.inactive {
  animation-name: fade-out;
  animation-duration: 0.6s;
  animation-fill-mode: forwards;
}

@keyframes fade-in {
    0% {
        opacity: 0;
        transform: translateX(-15px);
    }
    30% {
        opacity: 0;
    }
    60% {
        opacity: 1;
    }
    100% {
        opacity: 1;
        transform: translateX(0);
    }
}
@keyframes fade-out {
    0% {
        opacity: 1;
        transform: translateX(0);
    }
    30% {
        opacity: 1;
    }
    60% {
        opacity: 0;
    }
    100% {        
        transform: translateX(15px);
    }
}

Upvotes: 1

Related Questions