Custom components

What are custom components?

Native HTML elements are the built-in elements that are part of the HTML specification, such as the p element for a paragraph or the div element for a container. These elements are used to create the basic structure and content of a web page.

Custom React components, on the other hand, are user-defined components that are created using the React framework. These components allow you to reuse code and abstract complex UI elements into reusable pieces. They are typically defined using a combination of JavaScript and JSX, which is a syntax extension to JavaScript that allows you to write HTML-like syntax directly in your JavaScript code.

One key difference between native HTML elements and custom React components is that native HTML elements are passive, meaning they are rendered by the browser and cannot be changed or interacted with by your code. Custom React components, on the other hand, are active, meaning they can be manipulated and controlled by your code. This allows you to create more interactive and dynamic user interfaces.

Also, custom components have an internal state controlled by state management, which means that they will be updated when the value changes, however, native elements are not, because you can use a reference to the element to update its value.

Let's see some examples of custom components.

  • Datepikers - are a component that allows you to select a date.
  • Timepikers - are a component that allows you to select a time.
  • Sliders - are a component that allows you to select a range of values.
  • Selects, multi-selects components - are a component that allows you to select single or multiple values.
  • Drag and drop components - are a component that allows you to drag and drop items.

How to use custom components with useForm

To use custom components with useForm, you need to use the <Wrapper> component and pass the component as a prop. Another important thing is that the custom component should have those props: value, onChange, onBlur. The value prop is the value of the component, the onChange prop is the function that will be called when the value changes and the onBlur prop is the function that will be called when the component loses focus.

Why do we need to use the <Wrapper> component?

The register function is the only way to connect a field to the form, and the register function returns a reference to the component, then we need to use the <Wrapper> component to get the reference. Usually, custom components don't work with reference, in consequence, we need to use a wrapper to connect the custom component with a reference and finally connect to the form. And then you can use the register function to register the custom component.


  • The <Wrapper> component is a wrapper that will be used to wrap the custom component, it will be used to add the onChange and onBlur props to the native event handlers.
  • The <Wrapper> component is also used to add the value prop to the custom component.

How to use custom components with useField

When we are creating the form doesn't matter if we are using native HTML elements or not, it's just a function that creates a store and returns a function to manage the form. So we don't need to worry about it for now. We just need to create the form store, also we can provide the initial values, initial errors, initial touched, and the validation schema, but for now, we will just provide the initial values.

javascript
import { createForm } from '@use-form/core';
const useUserForm = createForm({
initialValues: {
names: [],
},
});

So, now we are going to create the form component that will be used to manage the form, and we will use the <Wrapper> component to wrap the custom component. All the props that the custom component will receive will be the props that the <Wrapper> component will receive.

To register the custom component, we will use the register function, and we will pass it to <Wrapper> component by the ref prop.

jsx
import { Wrapper } from '@use-form/use-form'
import Select from 'select-component'
funtion UserForm(){
const { register, handleSubmit } = useUserForm()
const onSubmit = (data) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Wrapper component={Select} {...register("names")} />
options={[
{ value: "John", label: "John" },
{ value: "Jane", label: "Jane" },
{ value: "Jack", label: "Jack" },
]}
/>
</form>
)
}

The wrapper component will look at the custom component props, and if the component doesn't have the following properties, onChange, onBlur, and value it will throw an error. In this case, you should build your own Wrapper component, or you can customize the component to add the onChange and onBlur props.