Languages

React / JSX - how to define functional component that accepts children with same attributes / props only?

2 points
Asked by:
Root-ssh
7514

I am working on some project where I need to create custom floating properties component.

Main idea is to create component that allows to put properties components as children.

I would like to allow to use different child components that accept same props.

Expected example usage:

<FloatingProperties>
  <FloatingTextProperty title="User name" value="John Doe" />       {/* text type */}
  <FloatingTextProperty title="User age" value="25" />              {/* text type */}
  <FloatingDateProperty title="Creation date" value="2020-07-01" /> {/* date type */}

  <Text title="Creation date" value="2020-07-01" /> {/* not allowed - not property component */}
</FloatingProperties>

I know how to do it with one child type:

// I use rebass library

type FloatingTextPropertyProps = {
  title: string;
  value: string;
};

const FloatingTextProperty = ({title, value} : FloatingTextPropertyProps) => {
  reutrn (
    <Box variant="floatingProperty">
      <Box variant="propertyTitle">{title}</Box>
      <Box variant="propertyValue">{value}</Box>
    </Box>
  );
};

type FloatingPropertiesProps = {
  children: FloatingTextProperty[]; // maybe, should I use some inheritance here?
};

type FloatingProperties = ({children} : FloatingPropertiesProps) => {
  reutrn (
    <Flex variant="floatingProperties">
      {children}
    </Flex>
  );
};

Is It possible to do it?

1 answers
1 points
Answered by:
Root-ssh
7514

Try to use ReactElement<MyProps, FunctionComponent<MyProps>> as type of children with your component.

Full example below:

import React, { ReactNode, FunctionComponent, ReactElement } from 'react';
import { Flex, Text } from 'rebass';


type MyProps = {
	title: string;
	value: ReactNode | string | number | boolean | null;
};

const MyValue = ({ title, value }: MyProps) => {
	return <Text title={title}>{value}</Text>;
};

const MyBoolean = ({ title, value}: MyProps) => {
	const text = title === 'true' ? 'Yes' : 'No';
	return <Text title={text}>{text}</Text>;
};


type MyChild = ReactElement<MyProps, FunctionComponent<MyProps>> | null;

type MyGroupProps = {
	children?: MyChild | MyChild[];
};

const MyGroup = ({ children }: MyGroupProps) => {
	return <Flex>{children}</Flex>;
};


const App = () => {
	return (
		<MyGroup>
			<MyValue title="Name" value="Kate" />
			<MyValue title="Occupation" value="Front-end developer" />
			<MyBoolean title="Active" value="true" />
		</MyGroup>
	);
};

Solution:

MyBoolean and MyValue components use the same props (MyProps). Later MyGroup uses as children components that uses MyProps defined by MyChild | MyChild[] - we allow for 0, 1, 2, 3, etc. children.

0 comments Add comment
Hey ūüĎč
Would you like to know what we do?
  • Dirask is online IT community for professionals and hobbyist to share their knowledge and help each other in extraordinary easy way.
  • We welcome everyone
    no matter what the experience,
    no matter how basic the question is,
    this community will help you.