Reputation: 73
import React from 'react';
import './App.css';
import Message from "./components/Message";
function App() {
return (
<div className="App">
<Message>
<p>Hello World</p>
</Message>
<Message>
<a>Hello World</a>
</Message>
<Message>
<button>Hello World</button>
</Message>
</div>
);
}
export default App;
import React, {FunctionComponent} from 'react';
interface OwnProps {
children: React.ReactElement<HTMLParagraphElement>;
}
type Props = OwnProps;
const Message: FunctionComponent<Props> = ({children}) => {
return (
<h1>
{children}
</h1>
);
};
export default Message;
The above code I can pass any HTMLElementTag as props.
Is there any way to restrict ReactElement to only specific element ?
For example only with p tag or button tag etc.
Upvotes: 0
Views: 1808
Reputation: 952
you can use following for static checking:
type Props = { children: React.ReactNode } //-- allow any React valid Node
// type Props = { children: never } //-- will not allow children to be passed
Upvotes: -1
Reputation: 323
You can render specific children with React.Children
by checking its type.
Below example only renders p tag elements.
import React, { Children } from "react";
interface Props {
children: React.ReactElement<HTMLParagraphElement | HTMLHeadElement>[] | React.ReactElement<HTMLParagraphElement | HTMLHeadElement>;
}
const Component: React.FC<Props> = ({ children }) => {
const elements = Children.map(children, (child) => {
if ((child as React.ReactElement).type === "p") {
return child;
}
return null;
})?.filter(Boolean);
return <div>{elements}</div>;
};
export default Component;
Note that type of custom component is a function, not string. And if you want to check types of nested html elements, you need to recursively check types of react elements children.
I do not know what you are trying to do here, but there may be a better approach than restricting render of children elements.
Upvotes: 2
Reputation: 933
I think this is the wrong way to be going about implementing HTMl here: if you want a <h1>
element to render then you shouldn't be passing <p>
or <button>
elements into it.
Why not just leave the functional component input here as just a string? Like so:
import React from 'react';
interface MessageProps {
messageText: string;
}
const Message: React.FC<MessageProps> = ({ messageText }) => {
return (
<h1>
{messageText}
</h1>
);
};
export default Message;
//////
import React from 'react';
import Message from "./components/Message";
function App() {
return (
<div className="App">
<Message messageText="Hello world" />
</div>
);
}
export default App;
Upvotes: 1