1

How do I get the li elements to fade in one by one in React? Note, I initially have the li display on none. Then, I plan to activate them when the mouse hovers over the ul word. The initial li will have opacity 0 but then I want the li to change one by one to opacity 1. How do I do this?

import React, { Component } from 'react';
import { Image } from 'semantic-ui-react'

class SideBar extends Component {
    state = {
        activeItem: '',
        displaying: false
    };
    mouseOver = () => {
        this.setState({displaying: true,activeItem: 'collapsed' });
    };
    mouseOut = () => {
        this.setState({displaying: false ,activeItem: '' });
    };  

    render() {
        const { activeItem, displaying } = this.state;
        let x = {
            a: {display: 'none'},
            b: {display: 'block'}
        }
        return(
    <header className="main-header">
        <div className="main-header-frame">
            <div className="header-wrapper">
                <nav 
onMouseLeave={this.mouseOut}
 onMouseOver={this.mouseOver}               
                className="main-navigation-container">
                    <ul className="main-navigation">
                        <li>

<a 
 href='/test'>Test1</a>

    <ul
className="t1"
style={Object.assign({},displaying && x.b, !displaying && x.a)
 >
                                <li>t1</li>
                                <li>t2</li>
                                <li>t3</li>
                                <li>t4</li>
                                <li>t5</li>
                            </ul>
                        </li>
                    </ul>
                </nav>
            </div>
        </div>
    </header>
            )
    }
};

export default SideBar;

My CSS is as follows:

.t1 > li {  
    opacity: .2;
    transition: all .8s ease-out;
    -webkit-transition: all .8s ease-out;
    -moz-transition: all .8s ease-out;
    -o-transition: all .8s ease-out;  
    transition-delay: .4s;      
}
.t1 > li:hover {    
    opacity: 1;
}

Maybe there's a way to do it by adding a classname to each li?

1 Answers1

0

IMHO there are two simple options, there are more but since the following two rely on css transitions only, no keyframe- or js-animation, I consider them as a simple approach for that problem.

1. Transitions Delay:

One needs to set the transition-delay for each element. Assuming items is an array of Objects that should be transformed into <li> elements.:

const TRANSITION_DURATION = 3; //in seconds, one needs to »know« this
                               //could be parsed from the css

items.map((item, idx) => 
  <li 
   key="…"
   className="fade-in-class" 
   style={transitionDelay: idx * TRANSITION_DURATION}>…</li>
);

So the Idea is: Increase the delay for each transition, such that the transitions appear one after the other. The downside is, that the Javascript needs to know about certain css values, the transition duration in this case.

2. Transition Events:

As described here there is at least one event, that is triggered when as transition is completed. That is a bit more complicated to code.

class FadeList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      itemToFade: 0
    }
  }

  render () {

    const toFade = this.state.itemToFade;

    return (<ul>
      {this.props.items.map((item, idx) => 
        <li
          key="…"
          className={idx == toFade ? 'fade-class' : ''  }
          onTransitionEnd={e => this.setState({itemToFade: toFade + 1})}
        >…</li>)}
    </ul>)
  }
}

The idea here is: Store the index of the Item to fade in next within the state of the component. When rendered, the css class that triggers the transition is added to only that element. When the transition is completed, the callback modifies the state, what in turn re-renders the component, with the next index. With that, the Javascript does not need to know any css values, what makes it easier to tweak those during a design iteration. Please note that code above is meant to just illustrate the idea, I have not tested.

Depending on the requirements, but if possible, the simplest solution to this maybe a pure css solution.

.transition {
   /* all the needed stuff here */
   transition-duration: 2s;
}

.transition:nth-child(2) {
  transition-delay: 2s;
}

.transition:nth-child(3) {
  transition-delay: 4s;
}

/* And so forth */

If you are using sass, you can generate the definitions for as much elements as you desire.

philipp
  • 15,947
  • 15
  • 61
  • 106