Search code examples
reactjsarraysstackrenderingsequence

Inserting a custom select element within a series of mapped input components in React


I'm working on a ReactJS project where I have an array of objects. Each object contains props data for a custom input component (<Input key={} type={} title={} group={}/>) I've built. My typical approach is to map over this array to render each of these input components.

However, I have a specific requirement for the rendered sequence of elements.
for example, If i need the rendered components to follow this order:

// start mapping the array and render <Input /> components
// --------------------------------------------------------------
<Input key={} type={} title={} group={}/>
<Input key={} type={} title={} group={}/>


// here i want to insert the Select Element in between the map sequence 
// --------------------------------------------------------------
<Select isActive={} options={} onChangeAction={} optionEvent={}/>

// continue the <Input /> components map sequence
// --------------------------------------------------------------
<Input key={} type={} title={} group={}/>
<Input key={} type={} title={} group={}/>
<Input key={} type={} title={} group={}/>

As you can see, I want to insert a custom select element (<Select />) in between the mapped <Input /> components. I'm trying to achieve this without heavily manipulating the original array or making the code less readable and maintainable.

Is there a conventional or recommended approach in React to map over an array while maintaining a specific order of rendered components, especially when inserting a different component within the sequence?

Any insights or best practices on this would be invaluable...

I incorporated a group key-value pair into the array that contains the prop data. This group key is processed through a reducer, which then assigns a specific className to the div wrapper of each rendered component.

However, I find this approach to be less intuitive and challenging to maintain. While I can employ this type of manipulation or iterate over multiple arrays to map out each group (with each array representing a distinct group), it feels cumbersome. This method requires excessive typing, which seems redundant and inefficient.


Solution

  • A couple of options (not really best practices, as those depend on the specific scenario) are

    a) You could either split the array to multiple one and then map over those (if it makes sense for your usecase)

    const allObjects = [...];
    const preSelect = allObjects.slice(0,5);
    const postSelect = allObjects.slice(5);
    
    // and when rendering do
    
    preSelect.map(...)
    <Select .../>
    postSelect.map(...)
    

    b) Alternatively, if you have a specific logic on where/when to show the select, you could return a Fragment with the Select and Input at that point.

    allObjects.map((object, index) => {
       if (/* condition to show select */){
        return <React.Fragment><Select .../><Input .../></React.Fragment>
       }
    
       return <Input .../>
    })
    

    A best practice would be to have your array correctly include the data you need to output the Select at the correct place just by iterating over it.

    Something like

    const allObjects = [
       ...,
       {type:'select', ...},
       ...
    ];
    
    // and then do
    
    allObject.map( object => {
      if (object.type === 'select'){
        return <Select .../>;
      }
      return <Input .../>;
    })