DEV Community

Eelco Verbrugge
Eelco Verbrugge

Posted on • Edited on

Create generic React components

As your application starts to grow, you often write repeated code. A simple example of this is with a form:

const SignupForm = () => {
  return (
    <form onSubmit={handleSubmit}>
      <label>Nickname</label>
      <input
        type="text"
        required
        onChange={handleChange}
        name="nickname"
        value={nickname} />

      <label>Email</label>
      <input
        type="email"
        required
        onChange={handleChange}
        name="email"
        value={email} />

      <label>Password</label>
      <input
        type="password"
        required
        onChange={handleChange}
        name="password"
        value={password} />

      <button type="submit">Submit</button>
    </form>
  )
}

export default SignupForm
Enter fullscreen mode Exit fullscreen mode

The combination of label + input is repeated 3 times with the same attributes but differences in some values.

Generic component

In order to reduce our code we'll create a new component FormInput where we group every label + input so we can reuse this code:

import React from 'react';

const INPUT_TYPE = {
    text: 'text',
    email: 'email',
    password: 'password',
}

const FormInput = ({ label, type, ...otherAttributes  }) => {

    if (!type) {
        throw Error('form input is missing the required type attribute');
    }

    return (
        <div>
            {label && (
                <label className="form-label">{label}</label>
            )}
            <input type={INPUT_TYPE[type]} className="form-input" {...otherAttributes} />
        </div>
    )
}

export default FormInput
Enter fullscreen mode Exit fullscreen mode

I've separate the label prop from all other attributes (...otherAttributes) which can be passed on, to keep it clean and readable. We'll check the label prop to make sure it exists, since maybe in the future we want to use an input without a label.

Now we can import our FormInput to our SignupForm, make sure your path is set right, so we can replace every label + input bij our FormInput component:

import FormInput from "./FormInput" // imports our component

const SignupForm = () => {
  return (
    <form onSubmit={handleSubmit}>
      <FormInput
        label="Nickname" // label prop with title as string
        type="text" // followed by all otherAttributes...
        required
        onChange={handleChange}
        name="nickname"
        value={nickname} />

      <FormInput
        label="Email"
        type="email"
        required
        onChange={handleChange}
        name="email"
        value={email} />

      <FormInput
        label="Password"
        type="password"
        required
        onChange={handleChange}
        name="password"
        value={password} />
    </form>
  )
}

export default SignupForm
Enter fullscreen mode Exit fullscreen mode

Congrats! You just created a generic component.

Top comments (0)