JSX.Element is not assignable to parameter of type ForwardRefRenderFunction
Asked Answered
R

2

6

I am trying to export a react but getting this TS error which I am unable to resolve.

Here is the component:

import React, {
  useEffect,
  MutableRefObject,
  forwardRef,
  RefObject
} from 'react';
import styled from 'styled-components';

export interface TextareaInputProps
  extends React.HTMLAttributes<HTMLTextAreaElement> {
  text?: string;
  onChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
  onApprove?: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;
}

export interface StyledTextareaInputProps {
  ref: MutableRefObject<HTMLTextAreaElement | null>;
}

const StyledTextArea = styled.textarea<StyledTextareaInputProps>`
  display: flex;
  align-items: stretch;
  resize: none;
  flex: 1;
  padding: ${({ theme }) => theme.padding.md}px;
  color: ${({ theme }) => theme.colors.grey700};
  line-height: ${({ theme }) => theme.lineHeights.nm};
  font-family: ${({ theme }) => theme.fontFamilies.regular};
  font-size: ${({ theme }) => theme.fontSizes.nm}px;
  font-weight: ${({ theme }) => theme.fontWeights.regular};
  text-overflow: ellipsis;
  border-style: none;
  border-color: transparent;
  overflow: auto;
`;

const TextareaInput = (
  { text, onChange, onBlur, onKeyDown, ...otherProps }: TextareaInputProps,
  ref: RefObject<HTMLTextAreaElement>
) => {
  useEffect(() => {
    if (ref && ref.current) {
      ref.current.focus();
    }
  }, [ref]);
  return (
    <StyledTextArea
      ref={ref}
      {...otherProps}
      onChange={onChange}
      value={text}
      onBlur={onBlur}
      onKeyDown={onKeyDown}
    />
  );
};

export default forwardRef(TextareaInput);

This is the error I am getting:

Argument of type '({ text, onChange, onBlur, onKeyDown, ...otherProps }: TextareaInputProps, ref: React.RefObject) => JSX.Element' is not assignable to parameter of type 'ForwardRefRenderFunction<HTMLTextAreaElement, TextareaInputProps>'. Types of parameters 'ref' and 'ref' are incompatible. Type 'MutableRefObject<HTMLTextAreaElement | null> | ((instance: HTMLTextAreaElement | null) => void) | null' is not assignable to type 'RefObject'. Type 'null' is not assignable to type 'RefObject'.

I have other components with a similar pattern which all works.

Reiff answered 1/9, 2020 at 12:49 Comment(0)
T
0

If you read react documentation about forwardRef:

The second ref argument only exists when you define a component with React.forwardRef call. Regular function or class components don’t receive the ref argument, and ref is not available in props either.

You need to do something like this:

const TextareaInput = (
  { text, onChange, onBlur, onKeyDown, ...otherProps }: TextareaInputProps,
  ref: RefObject<HTMLTextAreaElement>
) => {
  useEffect(() => {
    if (ref && ref.current) {
      ref.current.focus();
    }
  }, [ref]);
  return (
    <StyledTextArea
      ref={ref}
      {...otherProps}
      onChange={onChange}
      value={text}
      onBlur={onBlur}
      onKeyDown={onKeyDown}
    />
  );
};

First create ref:

const ref = React.createRef();

Second pass ref using forwardRef:

const ModifiedTextareaInput = React.forwardRef((props, ref) => <TextareaInput {...props} ref={ref}/>);
export default ModifiedTextareaInput;

Note: I have not added type defination for those. Assuming you can add those

Tease answered 1/9, 2020 at 13:2 Comment(2)
I am now getting a different error. Type '{ ref: ((instance: unknown) => void) | MutableRefObject<unknown> | null; props: { children?: ReactNode; }; }' is not assignable to type 'IntrinsicAttributes & TextareaInputProps'Reiff
I'm getting the same issue. @Reiff how did you solve the problem?Hillinck
G
1

As the error suggests, change your TextareaInput component into a ForwardRefRenderFunction, including the correct types. Remove the types from the parameters (this is important because you'll get another error otherwise).

Your updated function looks like this. Everything else stays the same:

const TextareaInput: ForwardRefRenderFunction<
  HTMLTextAreaElement,
  TextareaInputProps
> = (
  { text, onChange, onBlur, onKeyDown, ...otherProps },
  ref
) => {   
  useEffect(() => {
    if (ref && ref.current) {
      ref.current.focus();
    }
  }, [ref]);
  return (
    <StyledTextArea
      ref={ref}
      {...otherProps}
      onChange={onChange}
      value={text}
      onBlur={onBlur}
      onKeyDown={onKeyDown}
    />
  );
};
Gamete answered 14/4, 2023 at 11:21 Comment(1)
You are beautifulYusuk
T
0

If you read react documentation about forwardRef:

The second ref argument only exists when you define a component with React.forwardRef call. Regular function or class components don’t receive the ref argument, and ref is not available in props either.

You need to do something like this:

const TextareaInput = (
  { text, onChange, onBlur, onKeyDown, ...otherProps }: TextareaInputProps,
  ref: RefObject<HTMLTextAreaElement>
) => {
  useEffect(() => {
    if (ref && ref.current) {
      ref.current.focus();
    }
  }, [ref]);
  return (
    <StyledTextArea
      ref={ref}
      {...otherProps}
      onChange={onChange}
      value={text}
      onBlur={onBlur}
      onKeyDown={onKeyDown}
    />
  );
};

First create ref:

const ref = React.createRef();

Second pass ref using forwardRef:

const ModifiedTextareaInput = React.forwardRef((props, ref) => <TextareaInput {...props} ref={ref}/>);
export default ModifiedTextareaInput;

Note: I have not added type defination for those. Assuming you can add those

Tease answered 1/9, 2020 at 13:2 Comment(2)
I am now getting a different error. Type '{ ref: ((instance: unknown) => void) | MutableRefObject<unknown> | null; props: { children?: ReactNode; }; }' is not assignable to type 'IntrinsicAttributes & TextareaInputProps'Reiff
I'm getting the same issue. @Reiff how did you solve the problem?Hillinck

© 2022 - 2024 — McMap. All rights reserved.