Generate react.fragment for multiple items via function

Viewed 26

In the midst of me cleaning out a massive react render statement, I've been breaking some things out into helper functions. Here's a portion of what I have in a helper function:

// This looks ugly
return (
  <>
    {label}
    {getDropdown(
      daysOfWeek,
      handleDaysOfWeekChange,
      daysOfWeekLabel,
      options.dayOfWeek,
      isMultiSelectEnabled
    )}
  </>
);

The particulars of the getDropdown function don't matter. Label is a react component (and is defined as a variable since it's used elsewhere as well), and getDropdown returns a react component.

For some reason this just looks ugly to me, we start with a react.fragment so that we can have multiple javascript code snippets, but in turn each javascript snippet is either a variable which equals a react component, or a function which is computed at runtime to a react component. So we're really going from the react paradigm to javascript paradigm and then back to react.

I'd like something like this which is all javascript paradigm:

// invalid code!
return React.fillFragment(
  label,
  getDropdown(
    daysOfMonth,
    handleDaysOfMonthChange,
    daysOfMonthLabel,
    options.dayOfMonth,
    isMultiSelectEnabled
  ),
);

Returning an array just gives key errors, and we wouldn't want to overload this since there are other areas where we would want to return an array without a fragment.

The next best solution that I can think of is to simply treat these two as actual components, which would be the all react paradigm:

// Works, but still feels verbose
return (
  <>
    <Label/>
    <GetDropDown
      value={daysOfMonth}
      onChange={handleDaysOfMonthChange}
      defaultLabel={daysOfMonthLabel}
      listOptions={options.dayOfMonth}
      isMultiSelect={isMultiSelectEnabled}
    />
  </>
);

And this does work, but it feels a little overkill and isn't the most succinct for a couple one time use functions. (for example label is only used here and one other spot.)

I'm wondering is there something built in that I haven't been able to find, or is there a little trick here that I've never come across? Or maybe I'm being too picky

1 Answers

You last snippet look best to me.

If getDropdown returns a React component, then it is probably best for it to be a React component.

If you dislike <></> fragment syntax, you can put <Fragment></Fragment> instead.

If you want no fragment at all, you either have to inline your components Label and GetDropDown into their parent component. Or put Label into GetDropDown (GetDropDown should be renamed Dropdown by the way).

I don't know the content of GetDropDown and Label, but if there is nothing more than in a select and label, you may not want to create a React component.

If you have custom style applied to the label and select element, you can either add a global style sheet, or -preferred solution- use a css-in-js library like styled-components:

// Label is a component, with the custom style you define here.
const Label = styled.label`
  color: grey;
`;

Adding small components like that, has negligible performance cost.

Related