Languages

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

2 points
Asked by:
Root-ssh
91710

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 answer
1 points
Answered by:
Root-ssh
91710

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
Native Advertising
­čÜÇ
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

ÔŁĄ´ŞĆ­čĺ╗ ­čÖé

Join