Jack Moore

Email: jack(at)jmoore53.com
Project Updates

Breaking down static HTML/Javascript into Components for Reuse

09 Oct 2019 » react, frontend, components

Breaking down HTML and JS into Components for reuse

Try not to get lost in the code example below, but essentially what we have done is taken the original implementation of card which existed in the SomeTopLevelClass as JSX and we broke it into its simplest form, re-used as much as we could, and then refactored the code into multiple components.

The new implementation allowed us to see a cleaner version of the code and implement the card component over and over, changing a few top level variables with the changes seen allows us to pass our <Card> component with flexibility.

class SomeTopLevelClass {
    constructor(props){
        super(props)
    }
    render(){
        return(
            <React.Fragment>
                <Card 
                    planName="minimal" 
                    handleSuccessfulSubscribe={this.handleSuccessfulSubscribe}
                    handleSuccessfulUnsubscribe={this.handleSuccessfulUnsubscribe}
                    selectedPlans={this.state.selectedPlans}
                    deploymentStatus={this.state.deploymentStatus}
                />
                <Card 
                    planName="personal" 
                    handleSuccessfulSubscribe={this.handleSuccessfulSubscribe}
                    handleSuccessfulUnsubscribe={this.handleSuccessfulUnsubscribe}
                    selectedPlans={this.state.selectedPlans}
                    deploymentStatus={this.state.deploymentStatus}
                />
                <Card 
                    planName="personal_plus" 
                    handleSuccessfulSubscribe={this.handleSuccessfulSubscribe}
                    handleSuccessfulUnsubscribe={this.handleSuccessfulUnsubscribe}
                    selectedPlans={this.state.selectedPlans}
                    deploymentStatus={this.state.deploymentStatus}
                />
            </React.Fragment>
        )
    }
}


class Card extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            selectedPlans: this.props.selectedPlans,
            deploymentStatus: this.props.deploymentStatus
        }
    }

    render(){
        let name, price, description;
        switch(this.props.planName){
            case default:
                console.log("This hasn't been implemented")
        }
        return (
            <React.Fragment>
                <div className="card" style=>
                    <div className="card-body">
                        <h5 className="card-title">{name} Plan</h5>
                        <h6 className="card-subtitle mb-2 text-muted">{price}/Month</h6>
                        <p className="card-text">{description}</p>
                        <Button 
                            handleSuccessfulSubscribe={this.props.handleSuccessfulSubscribe}
                            handleSuccessfulUnsubscribe={this.props.handleSuccessfulUnsubscribe}
                            selectedPlans={this.state.selectedPlans}
                            deploymentStatus={this.state.deploymentStatus}
                            planName={this.props.planName}
                        />
                    </div>
                </div>
            </React.Fragment>
        )
    }
}

class Button extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            checked: false, 
            deploymentStatus: this.props.deploymentStatus,
            selectedPlans: this.props.selectedPlans
        }
        this.handleSuccessfulSubscribe = this.handleSuccessfulSubscribe.bind(this)
        this.handleSuccessfulUnsubscribe = this.handleSuccessfulUnsubscribe.bind(this)
        this.handleCheckboxButton = this.handleCheckboxButton.bind(this)
        this.handleSubscribe = this.handleSubscribe.bind(this)
        this.handleUnsubscribe = this.handleUnsubscribe.bind(this)
    }
    async handleUnsubscribe(e){
        //Method not shown
    }
    async handleSubscribe(e){
        //Method not shown
    }

    handleCheckboxButton(e){
        //Method not shown
    }

    handleSuccessfulSubscribe(){
        //Method not shown
    }

    handleSuccessfulUnsubscribe(){
        //Method not shown
    }

    render(){
        console.log(this.state.selectedPlans)
        let button;
        if(this.state.deploymentStatus == "pendingUnsubscribe"){
            button = (
                <div>
                    <b>Asset being decommissioned</b>
                </div>
            )
        }else if (this.state.selectedPlans.length == 0) {
            button = (
                <div>
                    <div className="card-link btn btn-light" style= onClick={(e) => this.handleSubscribe(e) } id="plan_individual">Select</div>
                    <a href="#" className="card-link">More Information</a>
                </div>
            )
        } else if (this.state.selectedPlans[0] == this.props.planName){
            // Probably need to break down button & modal into another react component
            // This disgusts me
            button = (
                <div>
                    </button>Simple button implementation that isnt shown</button>
                </div>
            )
        } else {
            let name;
            switch (this.state.selectedPlans[0]){
                case default:
                    console.log("This hasn't been implemented properly for blog's sake")
            }
            button = <div>You have selected the <span className="badge badge-primary">{name} plan!</span></div>
        }
        return(
            <React.Fragment>
                {button}
            </React.Fragment>
        )
    }
}

Takeaways

I didn’t go into much technical debt on this one. I think it’s partly because I have already encountered this issue before. This post is mostly here to make you think before you Google. This post is here to force you to double check your work and your errors before turning to Google. When changing 100’s of lines of code at once between classes, it is very easy to get lost and tangled up in the code.

At times when a major revision is coming to a codebase, it’s best to know what classes/components need what functionality and then move from there. Knowing the composition of components before and after will give you a plan to work from while implementing the changes.

Technical Debt

I wanted to go more into technical debt, but felt this wasn’t the appropriote post. (I think it was worth mentioning because this was going to need to be refactored one day or another.)

Technical debt is a concept often overlooked when building systems, but as maintenance becomes more and more prevelant in existing software projects, it is better to point out pieces of technical debt early to account for potential work that may arise.

Emotional Attachment to Code

Another important thing I walked away with was the thought that some code I write just sucks. The key with this is that I got it out of my system originally, and I went back and deleted/refactored it. I knew when I originally wrote the software I would have to refactor, I just never knew I would live to see the day..

© Jack Moore