Home > OS >  React Typescript children prop is defined in type props but somehow not picked up
React Typescript children prop is defined in type props but somehow not picked up

Time:07-13

I'm building a component library using React, TypeScript, Styled Components, and Rollup. Now I've created a Button component using a type interface. I then roll up the library to install it locally in my test project. I then import the Button and try to use it. I have defined two props for the button: children and type. Children is of type React.ReactNode, and type is of type String. Now when I use the Button component in my test project is keeps saying the following:

Type '{ children: string; type: string; }' is not assignable to type 'IntrinsicAttributes & ButtonProps'. Property 'children' does not exist on type 'IntrinsicAttributes & ButtonProps'.

Below is my type interface for the Button:

import React from "react";

export type ButtonProps = {
  type: String;
  children: React.ReactNode;
};

And below if my Button:

import React from "react";
import { ButtonBase } from "./button.style";
import { ButtonProps } from "./button.types";

function getButton(type: String) {
  switch (type) {
    case "base":
      return ButtonBase;
    default:
      return ButtonBase;
  }
}

const Button = ({ type, children }: ButtonProps) => {
  const Component = getButton(type);
  return <Component>{children}</Component>;
};

export default Button;

And this is how I then use the Button in my test project:

import { Button } from "aab-react-emerald";

function App() {
  return (
    <div className="App">
      <header className="App-header"></header>
      <Button type="base">Button</Button>
    </div>
  );
}

This is my ButtonBase. It is a Styled Component which inherits some styling from a basic Button component. There will be two more buttons, which both will inherit some default styling.

import styled from "styled-components";
import theme from "@theme";

const Button = styled.button`
  display: flex;
  justify-content: center;
  align-items: center;
  border: none;
  padding: 8px 16px;
  height: 40px;
  box-shadow: none;
  font-size: 16px;
  line-height: 24px;
  border-radius: 2px;
  cursor: pointer;
  transition: background-color ${theme.transition};
  transition: ${theme.transition};
`;

export const ButtonBase = styled(Button)`
  color: white;
  background-color: ${theme.colors.g300};

  :hover {
    background-color: ${theme.colors.g200};
  }

  :active {
    background-color: ${theme.colors.g400};
  }
`;

Does anyone know what I should do differently?

CodePudding user response:

In this code here

<Button type="base">Button</Button>

'children' is in fact a string, not a ReactNode - that's why it's getting rejected, the types don't match. If you allow a string in your type definition that should fix it:

children: React.ReactNode | string;

CodePudding user response:

You can define the component with the React.FC type, which adds the children prop to the props. For example:

import React from "react";
import { ButtonBase } from "./button.style";
import { ButtonProps } from "./button.types";

function getButton(type: String) {
  switch (type) {
    case "base":
      return ButtonBase;
    default:
      return ButtonBase;
  }
}

// Using FC there's no need to add the children props into ButtonProps
// as it is already defined in the FC.
const Button: React.FC<ButtonProps> = ({ type, children }) => {
  const Component = getButton(type);

  return <Component>{children}</Component>;
};

export default Button;

Here you have an interesting explanation about the React.FC type!

  • Related