I'm making a web app with React, Relay (experimental), and Typescript and I'm having some issues re-using components with similar data/props across different fragments.
Let's say I have the following Relay query and main app component:
const query = graphql`
query AppQuery {
currentUser {
...HomePage_currentUser
...ProfilePage_currentUser
}
}
`;
export default function App(): JSX.Element {
const appData = useLazyLoadQuery<AppQuery>(query, {});
return (
<>
<HomePage currentUser={appData.currentUser}>
<ProfilePage currentUser={appData.currentUser}>
</>
);
}
And the following page components:
interface HomePageProps {
currentUser: HomePage_currentUser$key | null;
}
const currentUserFragment = graphql`
fragment HomePage_currentUser on User {
id
profileImageUrl
items {
id
name
}
}
`;
export default function HomePage(props: HomePageProps): JSX.Element {
const currentUser = useFragment(currentUserFragment, props.currentUser);
return (
<>
{/* ... */}
<ProfileIcon user={currentUser} >
{/* ... */}
</>
)
}
interface ProfilePageProps {
currentUser: ProfilePage_currentUser$key | null;
}
const currentUserFragment = graphql`
fragment ProfilePage_currentUser on User {
id
profileImageUrl
lastLoggedInTimestamp
}
`;
export default function ProfilePage(props: ProfilePageProps): JSX.Element {
const currentUser = useFragment(currentUserFragment, props.currentUser);
return (
<>
{/* ... */}
<ProfileIcon user={currentUser} >
{/* ... */}
</>
)
}
And the following ProfileIcon
component
interface ProfileIconProps {
currentUser: ???
}
export default function ProfileIcon(props: ProfileIconProps): JSX.Element {
return (
<div>
<img src={props.currentUser.profileImageUrl} />
</div>
)
}
My main question is regarding the type of the currentUser
prop in the ProfileIcon
component. It seems like there's no clean way to re-use the component for a ProfilePage_currentUser
type and a HomePage_currentUser
type despite the data being requested being incredibly similar and it clearly being compatible for the sake of this component.
Is there any recommended way to handle this other than something like this?
interface ProfileIconProps {
currentUser: Omit<ProfilePage_currentUser, ' $refType'>
}