1

I am new to React and I want to see if my design logic is correct. I wish to animate a grid. A grid is composed of lines. Therefore, I have defined a <Grid /> component and a child component <Gridline \>. I figured that each <Gridline /> should handle its own animation logic. The <Grid \> parent component should be responsible for positioning the <Gridline /> components. After all of the <Gridline \>'s have finished animating, I want all of the gridlines to fade away. I figured this fade away logic should be handled by the <Grid /> component. However, in order for <Grid /> to begin animating it must know when each <Gridline /> has concluded animating. This requires each <Gridline /> communicating to <Grid /> when it has finished animating. I think this is considered bad-practice in React as data should flow from parent to child. My question is: Is my design logic good(for example having a Grid component and a Gridline child component), and if not, how can I refactor my code so that data flows from the parent component to the child component?.

Here is the full code for reference

Grid.js

class Grid extends React.Component {
   renderLines(numLines, offset, isRow) {
       let ruledPos;
       let offsetPos;
       let duration; 
       let delay;

       let spacing = Math.floor(100/numLines);
       let lineType = isRow ? 'row' : 'col';
       let lines = [];

       for (let i = 1; i <= numLines; i++) {
           ruledPos = offset + i * spacing;
           offsetPos = Math.random() * 100;
           duration =  100 + Math.random() * this.props.duration;
           delay = 700 + Math.random() * this.props.delay;
           lines.push(
               <Gridline 
                   key = {i + i*isRow}
                   lineType = {lineType} 
                   offsetPos = {offsetPos} 
                   ruledPos = {ruledPos}
                   duration = {duration}
                   delay = {delay}
               />
           );
       }                  
       return lines;
   }
   render() {
       let rowLines = this.renderLines(this.props.numLinesRow,
                                       this.props.offset,
                                       1);
       let colLines = this.renderLines(this.props.numLinesCol,
                                       this.props.offset,
                                       0);
       return(
           <CSSTransition
               in = {true}
               appear = {true}
               classNames = 'fade-out'
               timeout = {this.props.duration + this.props.delay}>
           <div className = 'grid' style = {{transitionDelay: `${300 + this.props.duration + this.props.delay}ms`}}>
               {rowLines}
               {colLines}
           </div>  
           </CSSTransition>
       );
   }
}

Grid.defaultProps = {
   numLinesRow: 15,
   numLinesCol: 23,
   offset: 0,
   duration: 1000,
   delay: 2000
};

export default Grid;

Gridline.js

import React from 'react';
import { CSSTransition } from 'react-transition-group';

class Gridline extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            showGridline: true, 
            hasEntered: false
        };
        if (this.props.lineType === 'row') {
            this.style = {'top': `${this.props.ruledPos}%`,
                            'left': `${this.props.offsetPos}%`, 
                        };
        } else {
            this.style = {'left': `${this.props.ruledPos}%`,
                            'top': `${this.props.offsetPos}%`};
        }
        this.style.transitionDuration = `${this.props.duration}ms`;
        this.style.transitionDelay = `${this.props.delay}ms`;
    }
    render(){
        return( 
                <CSSTransition
                in = {true}
                appear = {true}
                classNames = {`line-${this.props.lineType}`}
                timeout={this.props.duration + this.props.delay}
                >
                        <div 
                            className = "line"
                            style = {this.style}>
                        </div> 
                </CSSTransition>   
        );
    }
}

export default Gridline;

App.js


import React from 'react'

import './css/index.css'
import './css/materialize.css'

import Grid from './components/Grid.js'


class App extends React.Component{
    render() {
        return (
            <div id = 'App'>
                <Grid />
            </div>
        )
    }
}

export default App

0 Answers0