A Tip to Make Your React Code Better and Cleaner
Tags: react, javascript, webdev, bettercode
Published: 2020-06-08 01:22:27

Bootcamps are great at distilling a massive amount of information into a bite sized 15 week chunk to get you up to speed and ready to build entire web apps from scratch. However, what they aren't good at is affording you the time to really develop an application to its fullest potential. Of course real world work is a lot like that, time constraints and the pressure for a product mean cutting the full vision into something more manageable. 

Nevertheless, I'd recently returned to one of my favorite projects I'd done during my time at a bootcamp, a project called Virtual Canvas, and spent another three weeks completely overhauling the styling and flow of pages so that users had a more seamless, professional, and overall better designed experience that showcased what I'd worked so hard on.

Along the way, I'd converted all my CSS styling to SCSS or SASS and rather than bundling all the styling into one index.scss or app.scss file to work with, I took a more modular approach to styling and included scss right next to my javascript components. And honestly, this vastly improved my file structure and pushed me to think more like in a React way. This leads me to my current tip for vastly improving your approach to React code...

##Make it Inconvenient to Write Components

Let me explain. When I'd first began writing components in React, there was tendency not to treat components in a reusable way. It's almost as if you're writing new components whenever the need arises without heed towards whether you could actually accomplish more needs with one single component. Unfortunately, components are sometimes needless created for the sake of that moment rather than thoughtfully designed to scale or suit many different needs.

And when I'd chosen to bundle my js component with the accompanying sass file into an accurately named folder (ex. putting "Button.js" and "Button.scss" into a Button folder) it very much forced me to think of this component in a way that is reusable. Plus it adds wayyyy more steps to creating a component since you have to create several more files than just some javascript.

Also, this modular file structure is a visual reminder that this component holds its own insulated logic and is wholly different than the components written before it.

##How About a Use Case

When refactoring my original code, there were several instances of form components appearing in different areas of my React app. One form component for signing in, one for logging in, and so on. Obviously shooting through a three week project means you have to cut some corners, but I thought this was a good opportunity to write a form component. However, there were many forms throughout my app, including signin, login, or create canvas forms all with different labels and inputs and internal state.

However, they all sorta had similar logic within them, just with different names. This led me to write this form component that will change the internal state, labels, and inputs given different props I write in:

```Javascript
import React, { useState } from "react"
import "./Form.scss"

const Form = props => {
    const [data, setData] = useState({})

    const renderInputs = () => {
        return props.inputs.map(input => {
            return (
                <div className="field"> 
                    <label htmlFor={input.name} >{input.name}</label>
                    <input placeholder="" type="text" id={input.name} name={input.name} />
                </div>
            )
        })
    }

    const renderPassword = () => {
        if (props.hasOwnProperty("password")) {
            return (
                <div className="field">
                    <label htmlFor="password" >Password</label>
                    <input type="password" id="password" name="password"></input>
                </div>
            )
        }
    }

    const handleFormChange = (event) => {
        event.persist()
        const {name, value} = event.target
        setData({
            ...data,
            [name]: value
        })
    }

    const handleSubmit = (event) => {
        event.preventDefault()
        props.handleSubmit(data)
    }

    return (
        <form className="form" onChange={handleFormChange} onSubmit={handleSubmit}>
            {renderInputs()}
            {renderPassword()}
            <button type="submit" className="btn-secondary">{props.submitText}</button>
        </form>
    )
}

export default Form
```

I'll walk through from top to bottom now. We want to make each form controlled so this abstracted form component will start with an empty object as the internal state. The form will take in an "input" array as props as each of these array elements are objects that will construct each of our form inputs.

To render our input fields, we'll map through our input array and output label and input HTML tags and fill the HTML with things this input should describe (I used a name attribute and you can imagine that more specifications can be added to the input objects to specify the input HTML).

Also, since some of my forms required passwords and some didn't, I specified that this form component will accept a password prop that is a boolean. If the password prop is true then make a password field. Don't if false.

Here's what I thought was really cool. Since the state is currently an empty object, then how can state accurately change on to represent the changing form? Well, if we specify each input with name attribute, then the onChange event can pick up the correct input that's been changed completely abstracted away from what is actually in the form. The event will catch the current value and the name of the input, then log the name and the value into the state object. If the inputs were named the same at all then there would be foreseeable issues with this implementation but this can be easily avoidable.

Finally, the submit handler will just submit the data in state to a callback function we've passed down as props called "handleSubmit". This allows us to further abstract away specific implementation details in the form so that we can easily reuse the form across the app with little difficulty and enough customizability to suit our needs as the app scales.

##Conclusion

I think practicing with limitations on how many components you can create and even going so far as using a file structure where it's inconvenient to write more components will up you React game significantly. It's a good exercise and forces you into a mindset that approaches scalability and reusability in a good way.