korczas
korczas

Reputation: 87

How to prevent a prop from being passed to the extended component?

My question is similar to this one, however I need to type a component. I have tried a multiple ways, but still getting errors.

I am not sure if the problem is in my understanding, or am I doing something wrong? Here is what I tried:

import * as React from "react";
import TextareaAutosize, { TextareaAutosizeProps } from "react-textarea-autosize";
import styled from "styled-components";

interface Props {
  isActive?: boolean;
}

interface ExtendedProps extends Props, TextareaAutosizeProps {}

const FirstTry = styled(TextareaAutosize)<Props>`
  color: ${({ isActive }) => (isActive ? "red" : "blue")};
`;

const SecondTry = styled(({ isActive, ...rest }: ExtendedProps) => (
  <TextareaAutosize {...rest} />
))`
  color: ${({ isActive }) => (isActive ? "red" : "blue")};
`;

const ThirdTry = ({ isActive, ...rest }: ExtendedProps) => {
  const Foo = styled(TextareaAutosize)<TextareaAutosizeProps>`
    color: ${isActive ? "red" : "blue"};
  `;

  return <Foo {...rest} />;
};

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <FirstTry isActive minRows={3} />
      {/* FirstTry - Warning: React does not recognize the `isActive` prop on a DOM element */}
      <SecondTry isActive minRows={3} />
      <ThirdTry isActive minRows={3} />
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

Link to sandbox: https://codesandbox.io/s/zen-cdn-lp8pl?file=/src/App.tsx

Upvotes: 0

Views: 447

Answers (1)

J&#225;n Jakub Naništa
J&#225;n Jakub Naništa

Reputation: 1916

Your second approach looks good except for one small thing that causes the error: ref prop of TextareaAutosizeProps collides with ref prop of your styled component.

ref (and key for that matter) is a tricky "prop" - you pass it to a component just like any other props yet it does not appear in your props (if you log them for example), it is handled differently.

If you look at your second example:

const SecondTry = styled(({ isActive, ...rest }: ExtendedProps) => (
  <TextareaAutosize {...rest} />
))`
  color: ${({ isActive }) => (isActive ? "red" : "blue")};
`;

You can see that you are not styling TextareaAutosize but the anonymous function component ({ isActive, ...rest }: ExtendedProps) => .... If you pass ref to your SecondTry component it will not appear in your props ({ isActive, ...rest }: ExtendedProps). Yet when extending TextareaAutosizeProps you are also saying that there will be such a prop and it will be of type HTMLTextAreaElement.

So I can think of two solutions depending on your needs:

If you don't need the ref prop on your SecondTry you can just omit it from your props:

interface ExtendedProps extends Props, Omit<TextareaAutosizeProps, 'ref'> {}

If you need it though you will need to use React.forwardRef function (see more about that here).

Upvotes: 1

Related Questions