Having trouble with React Hook Form controlled input and typing

My application utilizes the react-hook-forms library along with the office-ui-fabric-react framework.

To integrate the framework inputs, I wrap the 3rd party component using the <Controller> element.

The current setup is functional as shown below:

<Controller
    control={control}
    name={"Value"}
    rules={{ required: true }}
    render={({ field, fieldState, formState }) => (
      <TextField
        value={field.value}
        errorMessage={fieldState.error?.message}
        label={field.name}
        description={"Value of the property"}
        onChange={(_, value) => field.onChange(value)}
        onBlur={field.onBlur}
        required
      />
    )}
  />

Since this method appears lengthy, I aim to streamline it by creating a new component called ControlledTextField.

I anticipate using it in the following way:


<ControlledTextField
    control={control}
    name={'Value'}
    rules={{ required: true }}
    label={'Value'}
    description={"Value of the property"}
    required
/>

In an attempt to implement this, I made the following adjustments:

type ControllerPropsEx = Omit<ControllerProps, "render" | "control" | "name">;

// Base type for controlled inputs
type ControlledType<F extends FieldValues, T> = {
  name: Path<F>;
  control: Control<F>;
  controllerProps?: ControllerPropsEx;
} & T;

// customized props for TextField component, merged with controller props 
// and excluding props already handled by react hook form
type ControlledTextFieldProps<F extends FieldValues> = ControlledType<
  F,
  Omit<ITextFieldProps, "onChange" | "onBlur" | "value" | "errorMessage"> // Exclude properties managed by the controller
>;

const ControlledTextField = <F extends FieldValues>({
  name,
  control,
  controllerProps,
  ...props
}: ControlledTextFieldProps<F>): JSX.Element => {
  return (
    <Controller
      name={name}
      control={control}
      {...controllerProps}
      render={({
        field: { onBlur, onChange, value, name },
        fieldState: { error }
      }) => (
        <TextField
          {...props}
          name={name}
          value={value || ""}
          onChange={onChange}
          onBlur={onBlur}
          errorMessage={error?.message}
        />
      )}
    />
  );
};

Despite these modifications, I encountered compile errors. Specifically, I received the

Type 'Control<F, any>' is not assignable to type 'Control<FieldValues, any>'
error relating to control={control}

How can I effectively categorize my component's prop types?

For a comprehensive code snapshot, visit the code sandbox repro (referencing NonWorkingForm.tsx file)

Answer №1

I identified the subtle issue at hand.

To solve it, I needed to pass a generic argument to ControllerProps in this manner:

type ControllerPropsCustom<F extends FieldValues> = Omit<
  ControllerProps<F>, // Added <F> as parameter here
  "render" | "control" | "name"
>;

// Core type for managing controlled inputs
type ManagedInputType<F extends FieldValues, T> = {
  name: Path<F>;
  control: Control<F>;
  customControllerProps?: ControllerPropsCustom<F>;
} & T;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

ANGULAR: Issue with filtering an array by clicking a button is not functioning

I've been attempting to apply a filter to my array by using modulo on the id when clicking multiple buttons. I initially tried using pipe but was advised to stick with .filter(). Despite watching numerous online tutorials, I keep encountering errors o ...

Mastering mapped types to replace properties in Typescript

I have created a Factory function where it takes an object as input and if that object contains specific properties, the factory transforms those properties into methods. How can I utilize mapped Types to accurately represent the type of the resulting obj ...

Testing the Compatibility of Angular JS and Angular 8 in a Hybrid Application

I am currently working on a hybrid application using AngularJS and Angular 8. The new components I create in Angular need to be downgraded for use in AngularJS. Here is a snippet of the module code: @NgModule({ // Declarations and Imports providers ...

The npm build command is triggering an error message that reads "Allocation failed due to ineffective mark-compacts near heap limit."

I'm currently working on a ReactJS/TypeScript project on Windows 10. I've been running into issues when trying to build my TypeScript scripts using the following command: "rimraf ../wwwroot/* && react-scripts-ts build && copyfi ...

Connecting two divs with lines in Angular can be achieved by using SVG elements such as

* Tournament Brackets Tree Web Page In the process of developing a responsive tournament brackets tree web page. * Connection Challenge I am facing an issue where I need to connect each bracket, represented by individual divs, with decorative lines linki ...

Stop useEffect from triggering during the first render

I'm working on implementing a debounce functionality for a custom input, but I'm facing an issue where the useEffect hook is triggered during the initial render. import { useDebouncedCallback } from "use-debounce"; interface myInputProps { ge ...

Angular2 plugin for redacting content

I'm attempting to integrate Redactor with additional plugins, but I'm encountering an issue where the counter plugin displays 0 words and 0 characters after the page has loaded. { words: 0, characters: 0, spaces: 0 } To address this pro ...

What is the best method for searching a string without considering uppercase or lowercase letters?

Here's a straightforward question I have: I need to search for a specific string match in a query. The code snippet is shown below: const test_name = 'ExAmPlE' const database_resources = await prisma.market.findMany({ where: { na ...

Tips for obtaining the most recent HTML element in Angular

I was able to include HTML content in an Angular (7) UI using the DomSanitizer this.sanitizer.bypassSecurityTrustHtml("htmlstr") Once the content is sanitized and displayed in the HTML view, users have the ability to modify the values as desired ...

FabricJS Canvas with a React DropDown Feature

While I have successfully created a TextBox on FabricJS Canvas, creating a Dropdown component has proven to be a challenge. The fabric.Textbox method allows for easy creation of text boxes, but no such built-in method exists for dropdowns in FabricJS. If y ...

Struggling to locate components in your React, Next.JS, and Typescript project? Storybook is having trouble finding them

I have set up Storybook with my Next.js, TypeScript, and React project. The main project renders fine, but Storybook is breaking and giving me the error message: "Module not found: Error: Can't resolve 'components/atoms' in...". It appears t ...

Experimenting with Date Object in Jest using Typescript and i18next

I have included a localization library and within my component, there is a date object defined like this: getDate = () => { const { t } = this.props; return new Date().toLocaleString(t('locale.name'), { weekday: "long", ...

What steps should I take to address conflicting type identifiers between Cypress and jQuery?

Currently, I am tasked with writing TypeScript end-to-end tests for an Angular 11 application. Following the recommended practices of Cypress, my test setup is encountering a conflict due to existing jQuery dependencies (3.5.1) in the app and Cypress (8.4. ...

Utilizing Typescript/React to Invoke Microsoft Graph Function and Validate M365 Group Owners

As a newcomer to React and TypeScript, I am eager to utilize the Microsoft Graph API in my React/TypeScript application to verify if the logged-in user is an owner of an M365 group. This is the code snippet I currently have: import { callMsGraph } from ...

How can I implement a recursive nested template call in Angular 2?

Hopefully the title isn't too misleading, but here's my dilemma: I am in the process of building an Angular 2 app and utilizing nested templates in multiple instances. The problem I am facing involves "widgets" within my app that can contain oth ...

Tips for securely passing props based on conditions to a functional component in React

I came across this situation: const enum Tag { Friday: 'Friday', Planning: 'Planning' } type Props = { tag: Tag, // tour: (location: string) => void, // time: (date: Date) => void, } const Child: React.FC<Props> = ...

What causes Enum[Enum.member] to be undefined in the TypeScript playground on codepen.io?

My intention was to test out some type settings on TypeScript playground at codepen.io, but I encountered an unexpected issue: enum Order { Asc = 'asc', Desc = 'desc' } console.log(Order[Order.Asc]); // undefined in codepen.io ...

Escape from the abyss of callback hell by leveraging the power of Angular, HttpClient, and

I'm currently grappling with understanding Angular (2+), the HttpClient, and Observables. I'm familiar with promises and async/await, and I'm trying to achieve a similar functionality in Angular. //(...) Here's some example code showca ...

Despite using Enzyme to locate a component again, the expected prop value is still not being returned

Two components are involved here - a modal and a button that is meant to open the modal by setting its isOpen prop to true. The initial state of the modal is set to false, but when the button is clicked, it should change to true. While everything works fi ...

Utilize Angular 2 Form Elements Again

I'm currently in the process of working on a project with Angular and I want to make sure that my form components can be used for creating and updating entities seamlessly. Let's say I have a User entity stored on a remote API, and I have a form ...