How to Design Compound Components With React Context
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the The newline Guide to Building a Company Component Library course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to The newline Guide to Building a Company Component Library, plus 70+ \newline books, guides and courses with the \newline Pro subscription.
[00:00 - 00:14] The patterns used in the previous module work well for simple standalone elements, but once you start creating patterns that share state between components, the additional logic is required. In this module, we will create a collection of form controls as compound components.
[00:15 - 00:27] These components will have a sure-to-react context provider that stores an auto -generated ID for accessibility. Compound components are a useful design pattern because they increase the flexibility of a component.
[00:28 - 00:38] Let's take a look at a traditional component API for a form field. Fields often have two DOM elements, a label and an input.
[00:39 - 00:50] These fields share a common ID which requires us to abstract the elements to a single component, in this case a form field. This API helps ensure a common layout but can lead to flexibility issues in the future.
[00:51 - 01:02] Without providing separate components for each DOM element, consumers are unable to change the order of elements or style them individually . It also makes it difficult to provide consistent props for each element.
[01:03 - 01:13] In this example, would an on-click event be for the label or input element? Providing separate components for each element allows consumers to reorder, style and apply props as needed.
[01:14 - 01:32] These compound components are able to use all of the shared API patterns that we went over in the previous modules, including children pass through, JSX prop spreading and the React Forward Ref API. In this case, both the label and input need access to a uniquely generated ID value to provide an accessible experience.
[01:33 - 01:41] This shared state can be provided using the context API. When rendered, the field component will generate a unique ID value and store it in local state.
[01:42 - 01:51] It will then use the context provider API to share the value with any consumers . In our label and input components, we will retrieve this value and apply it to the correct attributes.
[01:52 - 02:07] Generating a unique ID could become a common action throughout our component library, and we will be creating a custom utility hook that can be shared with other components in the future. In the next lesson, we'll be creating a new collection of field components and utilities which use this compound component pattern.