Search code examples
javascriptreactjsuser-input

What is the best way to render many input fields in React?


I am new to React, so I am sorry if this is very rudimentary. I haven't found a solution online for this exact problem before coming here.

Say I have to create a form with multiple input fields in a row, and I am using a .map() method over a data array to render these fields.

Something like this:

const inputData = [{label: "Name", placeholder: "Name"}, .....]

...More code...

<div> {inputData.map((data) => <UserInput label={data.label} placeholder={data.placeholder} />) </div>

However, the problem I am having is there should be other field types interspersed throughout the form, so that I cannot map through all of the inputData array without putting other fields at the end like a drop-down list, date picker, input fields with left and/or right add-ons, etc. Is calling the UserInput Component in the parent Component for each individual occurrence of an input the best method to go about this, even if there are many? Or is there a way I can still loop over the data and still have other fields in between the input fields, perhaps a different method altogether?


Solution

  • If I understand your question correctly, you have an array inputData which represents a series of inputs you'd like to include in your form, and you want those represented as <UserInput /> components; but you also have other input types you'd like to include as you see fit (radios, date pickers, etc).

    First, I suggest trying arellak's answer, as this may solve your problem, assuming you can handle all of the inputs as <UserInput /> components.

    However,

    In my opinion, it is odd to represent your <UserInput /> components as an array, especially if you have a fixed number of inputs. Instead of iterating over your array and rendering UserInputs, it is much better to hardcode them into the form component's return or render:

    return(
       <>
          <UserInput label={label1} placeholder={placeholder1}/>
          <UserInput label={label2} placeholder={placeholder2}/>
          <UserInput label={label3} placeholder={placeholder3}/>
          <UserInput label={label4} placeholder={placeholder4}/>
       </>
    );
    

    This has two advantages.

    1. It solves your problem. Now you can intersperse other types of inputs as you desire.
    2. It improves the readability of your code. Instead of iterating over an array and rendering components with other components mixed in, a reader of your code can clearly see what's going on. If you want to go back and tweak the layout of your component, it's clear to see exactly what that layout is.

    On the other hand, it's possible that you have a dynamic number of form elements (perhaps you're receiving inputData as a prop from a parent component).

    If that's the case, then I suggest you pass in your input components as children. Each time you create a form element, you pass in the inputs as child components.

    Parent component:

    <Form>
       <UserInput label={label1} placeholder={placeholder1}/>
       <UserInput label={label2} placeholder={placeholder2}/>
       <UserInput label={label3} placeholder={placeholder3}/>
       <UserInput label={label4} placeholder={placeholder4}/>
    </Form>
    

    Form component:

    const Form = ({children}) => {
       return (<div>{children}</div>);
    }
    

    Either way, I suggest you avoid using this array data structure unless you absolutely need to --- there are better, more readable ways to do it.