This video is available to students only


Our API for the Field will have two compound components, Label and Input.

The Field component will provide a unique ID to Field.Label and Field.Input using the Context API.

useUniqueID hook#

To generate our unique IDs we will be creating a custom React Hook using the Nano ID library. Nano ID is a powerful utility that is able to create URL-friendly unique strings. Let's add the library as a dependency:

Next, we need to create a new file for our hook. Since this utility can be useful for future component development we will place it in the utils folder.

Our unique IDs aren't required to be cryptographically secure so we are able to use the more performant non-secure import of Nano ID. We will also be creating a customAlphabet implementation to create a consistent ID structure that still has enough uniqueness to avoid potential collisions.

Our hook will generate a new ID when first rendered and return that same value throughout a consuming components lifecycle.

Field Context provider#

Our wrapping Field component will provide the value returned by useUniqueID through Context to its children. Create a new directory for the provider and its context:

Next, we can create a new FieldContext export that is typed to return a string (the unique ID) or undefined. This allows consumers to use the Field.Label and Field.Input components without a wrapper if necessary.

Our Field component will call the useUniqueID hook and provide that value to FieldContext.Provider.


Our Label component is built using the same techniques that we learned in the previous module. We need to include: children pass-through, JSX prop-spreading, and the forwardRef API. Let's create the initial component:

We are able to customize the displayName property to ensure that any errors reference the correct component name. Now we will retrieve the unique ID from FieldContext with the useContext hook. This value is applied to the htmlFor attribute.

No discussions yet