Intro Design patterns in software are helpful for many reasons, but two of the most important are that they give developers a shared vocabulary and offer solutions to commonly encountered problems. They are popularly used in OO languages but not so often thought of in React projects. In this article, I want to explore the Adapter pattern in React. In case you're not familiar with this pattern, I'll start with the classic object-oriented use case as an introduction. Then, I'll introduce an example of the Adapter pattern in action in a popular library. React By the end of the article, I want to be able to answer these two questions: What are some signals you should pay attention to when writing React components that point towards using the Adapter pattern? What are some characteristics of components that use the Adapter pattern? With that, let's get started! What is the Adapter Pattern? I'll be referring to the in this section. If you've never explored Refactoring Guru, it's a fantastic resource and is well worth your time. Adapter Pattern page from Refactoring Guru From this article, we can extract some key points to help us define the Adapter pattern: The Adapter pattern allows objects (or components) with incompatible interfaces to communicate with each other. The adapter hides the complexity of converting between interfaces by wrapping one of the objects. An adapter is especially useful when you can't - or don't want to - change the implementation details of an object to be compatible with another object. The example used by Refactoring Guru is one where you have a source of stock data in XML format and an analytics library that only takes in JSON data. The solution using the Adapter pattern is to wrap every interaction with the analytics library to take in the XML data, convert it to JSON, and send it to the appropriate methods of the library. Now that we've defined the Adapter pattern let's find a React example in the wild. Example in the Wild I use quite often because it simplifies the process of creating forms in React projects. It leans into normal HTML standards when it comes to form submissions and validation, which makes it feel natural to use. react-hook-form The most basic usage of react-hook-form involves the hook, which returns a function and a function. You connect the to the event on your form and connect the function to your form fields. I've linked to a CodeSandbox below, where I've set up a very basic form to illustrate this setup. useForm register handleSubmit handleSubmit onSubmit register https://codesandbox.io/embed/react-hook-form-simple-mc3ntk?fontsize=14&hidenavigation=1&theme=dark&embedable=true As you can see in the example, the function itself is designed to be used with inputs that have props for , , , and . register uncontrolled onChange onBlur name ref const { onChange, onBlur, name, ref } = register('firstName'); // include type check against field path with the name you have supplied. <input onChange={onChange} // assign onChange event onBlur={onBlur} // assign onBlur event name={name} // assign name prop ref={ref} // assign ref prop /> // same as above <input {...register('firstName')} /> What if you're trying to use a 3rd party or custom input that is and has non-standard event handlers? Luckily for you, react-hook-form includes the component that is designed for such use cases. This component is an example of the Adapter pattern in action because it has the ability to wrap any component with non-standard form behavior and make it compatible with other standard form fields. controlled Controller Controller Note one of our takeaways from the Adapter Pattern article from Coding Guru above: The Adapter pattern allows objects (or components) with incompatible interfaces to communicate with each other. Here, the component allows to communicate with basically any component that you would want to use in a form. Controller react-hook-form To see this in action, let's add on to the previous example form by adding a component to enter the username for the new user. Let's also pretend that we have some pre-existing component called that automatically checks to see if this username already exists in the system. This component is controlled since it automatically checks the entered username with the backend on every keystroke. It also has an prop that it only calls when a valid, available username has been entered. UsernameInput onValidUsername In order to use this component in our form powered by , we'll have to use the component to the behavior of the component to be compatible with the form. react-form-hook Controller adapt UsernameInput https://codesandbox.io/embed/react-hook-form-simple-username-mll5h9?fontsize=14&hidenavigation=1&theme=dark&embedable=true <Controller control={control} rules={{ required: true }} render={({ field }) => ( <UsernameInput onValidUsername={(username: string) => { field.onChange(username); }} /> )} name={"username"} /> In the above snippet, you can see where we've connected the function from the render prop of the component to the prop of our component. field.onChange Controller onValidUsername UsernameInput This brings up a key feature of using the Adapter pattern in React. Render props make your adapter infinitely more reusable because it allows the adapter to wrap any component. Imagine a different component that simply wrapped the form component instead of providing a render prop. In this case, you would have to have a different component for every form component that needed adapting. Render props! Controller Controller What signals in React apps point towards using the Adapter pattern? I think the most obvious is integrating 3rd party components into your application. Let's look at the as an example. This datepicker only accepts objects as props, but what if your server sends all dates as UTC timestamps? One possible solution using the Adapter pattern would look something like this: MUI Datepicker Date <UtcTimestampAdapter timestamp={timestamp} render={(localDate: Date) => ( <Datepicker defaultValue={localDate} /> )} /> In this example, the would handle converting the timestamp in UTC to the equivalent in the user's timezone, and pass it through the render prop where you can render the . Now you can easily render the with the correct date throughout your application! UtcTimestampAdapter Date Datepicker Datepicker Conclusion I hope after reading this article you can spot opportunities in your own React projects to use the Adapter pattern. You may even find that you've been using the pattern without realizing it! The benefit of learning to recognize and use design patterns is that it gives you and your team a common vocabulary when discussing or reading code. If you found this article helpful, let me know, and I'll write about other design patterns in React. Also published . here