Reputation: 2000
I am pretty new to typescript and am not sure how to best go about this rather common scenario. I fetch data and pass it into a template component as such:
const ProfilePage: FC = (): JSX.Element => {
const { data, isDataLoading } = useProfileData();
return (
<ProfileTemplate
data={!isDataLoading && data}
/>
);
};
This is the ProfileTemplate
component
import { profile_data, Maybe } from '../api-client';
type ProfileProps = {
data: Maybe<profile_data>;
}
export const ProfileTemplate: FC<ProfileProps> = ({ data }): JSX.Element => {
...
<StaticField label="First Name" text={data.first_name} />
<StaticField label="Last Name" text={data.last_name} />
...
}
Calling it as such results in Type 'false | Maybe<profile>' is not assignable to type 'Maybe<profile>'.
I can remove the conditional which checks isDataLoading
first, however I then get object is possibly null
errors in my <StaticField>
components.
first_name
and last_name
can be null or empty in the database. Although I realize that's not what's causing the object is possibly null
errors, rather an empty profile_data
object, when no data has been returned from the server yet.
How should I best handle this situation?
My `<StaticField>` component looks like so: interface Props {
label: string;
text?: Maybe<string>;
}
export const StaticField: FunctionComponent<Props> = ({ label, text }): JSX.Element => {
return (
<Box>
<Text color="gray.BlackCoral" className={classes.label}>
{label}
</Text>
<Text>{text}</Text>
</Box>
);
};
Upvotes: 0
Views: 1081
Reputation: 6112
If I understand it correctly, Maybe
seems to have been defined like type Maybe<T> = T | null
.
So, since you expect data
to be either present or null
, you can change your consumption logic to
<ProfileTemplate
data={isDataLoading ? null : data}
/>
This will get rid of the error 'false | Maybe<profile>' is not assignable to type 'Maybe<profile>'.
. This error shows up because in your existing code !isDataLoading && data
can either evaluate to false
or whatever the type of data
is.
Secondly, since data
can be null
, using it to access data.first_name
can be a problem. That's what TypeScript is trying to tell you. One way to "fix" it would be to use the optional chaining data?.first_name
to tell the compiler that you'll access first_name
iff data
is defined.
Upvotes: 0
Reputation: 1104
This line here is the problem
data={!isDataLoading && data}
I suggest you refactor your code to have conditional render like so
if (isDataLoading || !data) {
return null
}
return (
<ProfileTemplate data={data}/>
);
However you can simply replace the data prop with a ternary It is always good practice to extract into constants
const data = isDataLoading ? data : undefined;
return (
<ProfileTemplate data={data}/>
);
The second option still does not account for what should be rendered when you have data undefined So you would need a render of null inside ProfileTemplate
Upvotes: 1
Reputation: 12787
You should handle like this to make sure ProfileTemplate
always has data
{
!isDataLoading && <ProfileTemplate data={data} />;
}
Upvotes: 1