-
Notifications
You must be signed in to change notification settings - Fork 39
Description
Is your feature request related to a problem? Please describe.
Webpages commonly need to conditionally render content only if a content field has a value. For example, you may only want to render an <h1> element if a Title field has a value.
This can currently be accomplished with @prismicio/client's isFilled set of helpers:
import { isFilled } from "@prismicio/client";
import { PrismicRichText } from "@prismicio/react";
export function MySlice({ slice }) {
return (
<section>
{isFilled.richText(slice.primary.title) ? (
<h1>
<PrismicRichText field={slice.primary.title} />
</h1>
) : (
<div>Some fallback</div>
)}
</section>
);
}While the above code works, it is verbose and feels procedural.
Describe the solution you'd like
A dedicated React component that accomplishes the same as above in a declarative way would be an improvement.
import { IsFilled, PrismicRichText } from "@prismicio/react";
export function MySlice({ slice }) {
return (
<section>
<IsFilled.RichText
field={slice.primary.title}
fallback={<div>Some fallback</div>}
>
<h1>
<PrismicRichText field={slice.primary.title} />
</h1>
</IsFilled.RichText>
</section>
);
}Although the above code is not more concise than the isFilled.richText() version (it is actually more characters), it is easier to read and edit. The React syntax fits in with the surrounding code better than the ternarry and isFilled helper.
This solution can be ported to other integration libraries, like @prismicio/vue and @prismicio/svelte.
Type Narrowing
isFilled narrows the type of the provided field. After narrowing the field, you can be sure that the field is filled, and you will get autocompletion that suggests that.
When using JSX, you will not get that effect because TypeScript doesn't support type predicates in JSX (see Using type predicates).
To get around that limitation, we may need to introduce a dedicated render prop (render={(field) => {...}}) or render prop via children (i.e. (field) => {...}) rather than supporting children directly.
import { IsFilled, PrismicRichText } from "@prismicio/react";
export function MySlice({ slice }) {
return (
<section>
<IsFilled.RichText
field={slice.primary.title}
fallback={<div>Some fallback</div>}
>
{(field) => (
<h1>
<PrismicRichText field={field} />
</h1>
)}
</IsFilled.RichText>
</section>
);
}Or...
import { IsFilled, PrismicRichText } from "@prismicio/react";
export function MySlice({ slice }) {
return (
<section>
<IsFilled.RichText
field={slice.primary.title}
render={(field) => (
<h1>
<PrismicRichText field={field} />
</h1>
)}
fallback={<div>Some fallback</div>}
/>
</section>
);
}Either case may not work in Server Components since it passes a function.
Describe alternatives you've considered
isFilledhelpers, as described above.- Pre-process query results to bake metadata into values. For example, a key text field could have a hidden
_hasValuecomputed property that tells us if it is filled. Pre-processing content requires access to the type JSON definitions, which is not available on the client. - Build-time generated that creates
isFilledhelpers specific for your content. It's not clear exactly what this is yet.
Additional context
N/A