3

I have a table rendered with react (about 100 rows), but I would like the effect of the rows appearing one by one. Is there a way to do this with React? Below is my React code (the derivePairs funtion on the willMount procedure comes up with the data for the table).

var columns = [
      { key: 'pairNo', label: 'Zaporedna številka' },
      { key: 'homeTeam', label: 'Domača ekipa' },
      { key: 'awayTeam', label: 'Gostujoča ekipa' },
      { key: 'score', label: 'Rezultat' }
  ];

  var Table = React.createClass({

      getInitialState: function() {
        return {data: this.props.data};
      },

      componentWillMount: function() {
        derivePairs();
      },

      render: function() {
          var headerComponents = this.generateHeaders(),
              rowComponents = this.generateRows();

          return (
              <table>
                  <thead>{headerComponents}</thead>
                  <tbody>{rowComponents}</tbody>
              </table>
          );
      },

      generateHeaders: function() {
          var cols = this.props.cols;  // [{key, label}]

          // generate our header (th) cell components
          return cols.map(function(colData) {
              return <th key={colData.key}>{colData.label}</th>;
          });
      },

      generateRows: function() {
          var cols = this.props.cols,  // [{key, label}]
              data = this.props.data;

          var round=1;
          var pairNo=1;
          var oldRound=0;
          var teamName=null;
          return this.state.data.map(function(item, i) {
              // handle the column data within each row
              var htmlExcerpt = null;
              var len = Object.keys(cols).length;
              if (oldRound !== item.round) {
                  i=i+1;
                  htmlExcerpt = <tr key={'round'+item.round}><td colSpan={len}>Round: {item.round}</td></tr>;
                  oldRound = item.round;
              }
              var cells = cols.map(function(colData) {
                  console.log(colData);
                  // colData.key might be "firstName"
                  if (colData.key == "pairNo") {
                    return (<td> {pairNo} </td>);
                  } else {
                    if (colData.key == "homeTeam" || colData.key == "awayTeam") {
                      teamName = config.teams[item[colData.key]].name;
                      return (<td> {teamName} </td>);
                    } else {
                      return (<td> {item[colData.key]} </td>);
                    }
                  }
              });
              if (htmlExcerpt !== null) {
                return [htmlExcerpt,<tr className=enter-data key={i}> {cells} </tr>];
              } else {
                return <tr className=enter-data key={i}> {cells} </tr>;
              }
              pairNo=pairNo+1;
          });
      }
  });

  ReactDOM.render(<Table cols={columns} data={config.pairs}/>, document.getElementById('roundPairs'));

Thanks for the help.

Bostjan
  • 1,397
  • 3
  • 21
  • 36

1 Answers1

2

You can achieve this by using ReactCSSTransitionGroup package.

Your render method should be like this:

// ...

render: function() {
    var headerComponents = this.generateHeaders(),
        rowComponents = this.generateRows();

    return (
        <table>
            <thead>{headerComponents}</thead>
            <ReactCSSTransitionGroup
              transitionName="fade"
              transitionEnterTimeout={500}
              transitionLeaveTimeout={300}
              transitionAppearTimeout={500}
              transitionAppear={true}
              component="tbody"
            >
              {rowComponents}
            </ReactCSSTransitionGroup>
        </table>
    );
},

// ...

Next, you should define css classes. For fade animation name, they should be:

.fade-enter {
  opacity: 0.01;
}

.fade-enter.fade-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}

.fade-leave {
  opacity: 1;
}

.fade-leave.fade-leave-active {
  opacity: 0.01;
  transition: opacity 300ms ease-in;
}

.fade-appear {
  opacity: 0.01;
}

.fade-appear.fade-appear-active {
  opacity: 1;
  transition: opacity .5s ease-in;
}
1ven
  • 6,776
  • 1
  • 25
  • 39
  • Thanks for helping, but even after doing so it's still just showing up without any fade effects. The table just instantly appears. Please check it out at: http://bobr.si/react/index_new.html – Bostjan Aug 05 '16 at 14:05
  • @Bostjan, it's looks like you haven't wrapped rows with `ReactCSSTransitionGroup` component. It's difficult to understand, not seeing your current code. Could you upload it on pastebin.com? – 1ven Aug 05 '16 at 14:11
  • Thanks for being so helpful...I've also uploaded the code to pastebin: http://pastebin.com/dWnay05w althought you can also see it in the source code of that link I posted in my first comment – Bostjan Aug 05 '16 at 14:18
  • This [solution](http://stackoverflow.com/a/38725097/5157454) might also work in your case. The issue is the same - how to animate elements one after the other in the initial render. – Ori Drori Aug 05 '16 at 14:48
  • @Bostjan, sorry, initially I forgot to add `transitionAppearTimeout` and `transitionAppear` props to `ReactCSSTransitionGroup`. Also, you should add corresponding classes. See updated answer. – 1ven Aug 05 '16 at 14:51
  • @Bostjan, also, I've simplified your example. See http://codepen.io/1ven/pen/jAZxPG working example in action. – 1ven Aug 05 '16 at 14:54
  • Great! It works now...thank you. Just one more question if I may...is it possible to achieve an effect of rows fading in one by one? I think @Ori Drori suggested it in his comment. – Bostjan Aug 05 '16 at 15:24
  • @OriDrori Just wanted to ask you why the different quotes in this line: style={{ 'transition-delay': `${index * delay}ms` }} – Bostjan Aug 06 '16 at 12:08
  • The quotes are for ES6 template literals. – Ori Drori Aug 06 '16 at 22:32
  • @OriDrori just wanted to follow up on this...your line displays a warning: Unsupported style property transition-delay. Did you mean transitionDelay? It works, but just wanted to know if there is another way to do it? – Bostjan Aug 11 '16 at 14:17
  • Indeed you're right, and it should be `transitionDelay`. Fixed that. Thanks. – Ori Drori Aug 11 '16 at 20:47