我的问题是对这个高度赞成的问题的澄清/更新:
何时使用 JSX.Element、ReactNode、ReactElement?
在我看来,当您想要拥有返回字符串、null 等原语的函数组件时,TypeScript 不会很好地发挥作用。
例如,假设您有一个需要渲染道具的组件:
import React from "react";
type User = {
id: string;
name: string;
imgSrc: string;
}
type UserProfilePageProps = {
RenderUserPanel: React.ComponentType<{user: User}>;
}
export const fetchUser = async () : Promise<User> => {
return {
id: "123",
imgSrc: "placeholdit",
name: "Joe Bloggs"
}
}
const UserProfilePage = (props: UserProfilePageProps) => {
const {RenderUserPanel} = props;
const [user, setUser] = React.useState<null |User>(null);
React.useEffect(()=> {
fetchUser().then(user => setUser(user));
}, []);
return <section>
<h2>User Details</h2>
{user && <RenderUserPanel user = {user}/>}
</section>
}
现在我可以创建组件,这些组件应该以四种不同的方式实现这个渲染道具:
class ClassBasedUserPanel extends React.Component<{user: User}> {
render() {
return <div>
{this.props.user.name}
</div>
}
}
class ClassBasedUserPanelThatReturnsString extends React.Component<{user: User}> {
render() {
return this.props.user.name;
}
}
const FunctionBasedUserPanel = (props: {user: User}) => {
return <div>
{props.user.name}
</div>
}
const FunctionBasedUserPanelThatReturnsString = (props: {user: User}) => {
return props.user.name;
}
但是,这FunctionBasedUserPnelThatReturnsAString
不合适 React.ComponentType<{user: User}>;
,因为React.FunctionComponent
必须返回React.ReactElement
一个字符串不是的。
React.ClassComponent
另一方面,没有这个约束。
const Main = () => {
return <div>
<UserProfilePage RenderUserPanel = {ClassBasedUserPanel}/>
<UserProfilePage RenderUserPanel = {ClassBasedUserPanelThatReturnsString}/>
<UserProfilePage RenderUserPanel = {FunctionBasedUserPanel}/>
{/* ERROR! */}
<UserProfilePage RenderUserPanel = {FunctionBasedUserPanelThatReturnsString}/>
</div>
}
本质上,我想要的是一种类型:
type TypeImLookingFor<P = {}> = React.ComponentType<P> | (props: P) => ReactNode;
这存在吗?有没有理由不应该存在?
注意:我目前正在使用 React 16。也许这是在 React 17 或 18 中修复的问题。