Skip to main content

3rd-Party UI Libraries

Life is hard but coding can be easier. The reason we ❤️ open-source software (OSS) is because there're many awesome libraries that help us making a better world by software products. React Cool Form bears the faith in mind, it allows us integrate with any 3rd-party UI libraries easily. There're three ways to integrate with an UI library in React Cool Form.

1. Seamless Integration#

Uncontrolled components or components that rely on native input elements (i.e. input, select, and textarea) to work under the hood, we need to do nothing 😂. For example: Material-UI's TextField, Checkbox, and Select, etc.

Edit RCF - Material-UI

import { useForm } from "react-cool-form";import {  FormControl,  FormControlLabel,  FormLabel,  InputLabel,  TextField,  Select,  Checkbox,  Button,} from "@material-ui/core";
const App = () => {  const { form, use } = useForm({    defaultValues: { username: "", framework: "", fruit: [] },    onSubmit: (values) => console.log("onSubmit: ", values),  });  const errors = use("errors");
  return (    <form ref={form} noValidate>      <TextField        label="Username"        name="username"        required        error={!!errors.username}        helperText={errors.username}      />      <FormControl>        <InputLabel htmlFor="framework">Framework</InputLabel>        {/* When working with select, we need to enable the native select element or you can use the "NativeSelect" instead */}        <Select inputProps={{ id: "framework", name: "framework" }} native>          <option aria-label="None" value="I'm interesting in..." />          <option value="react">React</option>          <option value="vue">Vue</option>          <option value="angular">Angular</option>          <option value="svelte">Svelte</option>        </Select>      </FormControl>      <FormControl component="fieldset"></FormControl>      <div>        <FormLabel component="legend">Fruit</FormLabel>        <FormControlLabel          control={<Checkbox />}          name="fruit"          value="🍎"          label="🍎"        />        <FormControlLabel          control={<Checkbox />}          name="fruit"          value="🍋"          label="🍋"        />        <FormControlLabel          control={<Checkbox />}          name="fruit"          value="🥝"          label="🥝"        />      </div>      <Button type="submit" variant="contained" color="primary">        Submit      </Button>    </form>  );};

2. useControlled Hook#

Controlled components with highly customized and full features like React Select or React Datepicker. We can use React Cool Form's useControlled hook to create a reusable controller component for them in a flexible and performant way.

note

When using the hook (and not working with field-array), a default value is required.

Edit RCF - React Select

import { useForm, useControlled } from "react-cool-form";import Select from "react-select";
const Field = ({ as, name, ...restProps }) => {  const [fieldProps] = useControlled(name, restProps);  const Component = as;
  return <Component {...fieldProps} />;};
const options = [  { label: "React", value: "react" },  { label: "Vue", value: "vue" },  { label: "Angular", value: "angular" },  { label: "Svelte", value: "svelte" },];
const App = () => {  const { form } = useForm({    defaultValues: { framework: "" }, // We must provide a default value for the controlled field    excludeFields: ["#framework"], // Exclude the internal input element of React-Select by ID    onSubmit: (values) => console.log("onSubmit: ", values),  });
  return (    <form ref={form}>      <Field        as={Select}        name="framework"        inputId="framework" // Used for excluding the internal input element of React-Select        options={options}        parse={(option) => option.value}        format={(value) => options.find((option) => option.value === value)}      />      <input type="submit" />    </form>  );};

3. Do It Yourself#

If the above solutions can't meet your needs then you can set up a custom field with the API of React Cool Form. The following example demonstrates how to combine the useFormState and useFormMethods to DIY a custom field with full validation UX.

Edit RCF - Custom Field

import { useForm, useFormState, useFormMethods } from "react-cool-form";import { TextField, Button } from "@material-ui/core";
const Field = ({ as, name, onChange, onBlur, ...restProps }) => {  const value = useFormState(`values.${name}`);  const { setValue, setTouched } = useFormMethods();  const Component = as;
  return (    <Component      name={name}      value={value}      onChange={(e) => {        setValue(name, e.target.value); // Update the field's value and set it as touched        if (onChange) onChange(e);      }}      onBlur={(e) => {        setTouched(name); // Set the field as touched for displaying error (if it's not touched)        if (onBlur) onBlur(e);      }}      {...restProps}    />  );};
const App = () => {  const { form, use } = useForm({    defaultValues: { username: "" },    // excludeFields: ["username"], // You can also exclude the field here    validate: ({ username }) => {      const errors = {};      if (!username.length) errors.username = "Required";      return errors;    },    onSubmit: (values) => console.log("onSubmit: ", values),  });  const errors = use("errors");
  return (    <form ref={form} noValidate>      <Field        as={TextField}        label="Username"        name="username" // Used for the "excludeFields" option        required        error={!!errors.username}        helperText={errors.username}        inputProps={{ "data-rcf-exclude": true }} // Exclude the field via the pre-defined data attribute      />      <Button type="submit" variant="contained" color="primary">        Submit      </Button>    </form>  );};