DEV Community

Cover image for Dynamic Name React Component With Closure
Zulfan Hameed
Zulfan Hameed

Posted on • Edited on

Dynamic Name React Component With Closure

I was going through the react course on @FrontendMasters by @holtbt and I noticed how he used a custom hook to return a closure of react component, it's state object and the state modifier to create a reusable component.

When I want to create a component for rendering similar elements with different data I just go ahead a create a component which excepts the dynamic data as props.
Let's take an example where we want to create multiple dropdown elements with different options. I would go ahead and create a component something like this

// DropdownElement.js
import React, { useState } from 'react';

const DropdownElement = props => {
  const { dropdownLabel, options } = props;
  const [selectedValue, updateSelectedValue] = useState(options[0]);
  return (
    <>
      <label htmlFor={dropdownLabel}>
        {dropdownLabel}
      </label>
      <select
        id={dropdownLabel}
        value={selectedValue}
        onChange={e => updateSelectedValue(e.target.value)}
        onBlur={e => updateSelectedValue(e.target.value)}
        disabled={!options.length}
      >
        {options.map(item => (
          <option key={item} value={item}>
            {item}
          </option>
        ))}
      </select>
    </>
  );
};

export default DropdownElement;

Now if we want to create any dropdown element, we can use <DropdownElement /> passing in props with it.
Let's say we want to create a filter component for shoes which has Color and Size dropdown fields.

//shoeFilter.js
import React from 'react';
import DropdownElement from './DropdownElement';

const ShoeFilter = () => (
  <>
    <DropdownElement
      dropdownLabel="Shoe Color"
      options={["black", "red", "white"]}
    />
    <DropdownElement
      dropdownLabel="Shoe Size"
      options={["6", "7", "8", "9", "10"]}
    />
  </>
);

export default ShoeFilter;

This will create two dropdowns Shoe Color and Shoe Size. This is what people generally do, or at least this is what I do. There is nothing wrong with it. But, what if we could give the composite component <DropdownElement /> any name we want when we use it? Say for Shoe Color we could call it with <ShoeColorDropdown /> and for Shoe Size it could be <ShoeSizeDropdown /> This would certainly increase readability. So how can we do this?

import React, { useState } from 'react';

const useDropdown = (dropdownLabel, options) => {
  const [selectedValue, updateSelectedValue] = useState(options[0]);
  const DropdownComponent () => (
    <>
      <label htmlFor={dropdownLabel}>
        {dropdownLabel}
      </label>
      <select
        id={dropdownLabel}
        value={selectedValue}
        onChange={e => updateSelectedValue(e.target.value)}
        onBlur={e => updateSelectedValue(e.target.value)}
        disabled={!options.length}
      >
        {options.map(item => (
          <option key={item} value={item}>
            {item}
          </option>
        ))}
      </select>
    </>
  );
  return DropdownComponent;
};

const ShoeFilter = () => {
  const ShoeColorDropdown = useDropdown("Shoe Color", ["black", "red", "white"]);
  const ShoeSizeDropdown = useDropdown("Shoe Size", ["6", "7", "8", "9", "10"]);
  return (
    <>
      <ShoeColorDropdown />
      <ShoeSizeDropdown />
    </>
  );
};

So what is happening here is I am giving a name to the closure which is returned when useDropdown() is invoked and since that closure returns a react component we can go ahead and render it.

Now I have used this component just to render some data, we can extend this by returning an array of objects related to the component like its state and state modifier so the parent component can directly access the component data and maybe also change it. This is a custom hook and the next post will explain it well. I will update on twitter once it's out, please show me some love there :P

Let me know your thought's.

If anyone is getting started with react, this course on @FrontendMasters by @holtbt is a great starting point. I got the idea for this pattern from his lecture. Also, the subscription to Frontend Masters is really really worth it. The quality of content is just amazing. Kudos to @1Marc for putting together an amazing platform.

Top comments (2)

Collapse
 
alvechy profile image
Alexander Vechy • Edited

The problem with the hook approach is that you actually don't solve any problem. Performance-wise DropdownElement written as component is parsed by the engine once, while inside the hook function for DropdownComponent is allocated on every hook call. While ofc the effect is very little, there is no benefit that can out-weight the loss.

Collapse
 
parfectshot profile image
Paritosh

Exactly! Writing custom hooks just for readability while compromising with the performance is not a good approach.

I would've loved if there was some actual problem-solving in this post.