Skip to main content

Dependent Finder.Content components

User story: Max McHacker needs to select reported issues to forward to the dev team.

We need to track selected issue ids in state, and provide a form to submit the selection.

Welcome to CypressPine systems, Max.
0/5 issue(s) selected

Define the context shape

First, we need to inform Finder what our context will look like.

interface IssueTrackerContext {
isSelected: (id: string) => boolean;
toggle: (id: string) => void;
}

Memoize context reference

Like any React object prop, you'll want to memoize the context to reduce re-renders.

function IssueTracker() {
const items = useGetIssues();
const [selectedItemIds, setSelectedItemIds] = useState<string[]>([]);
const context: IssueTrackerContext = useMemo(() => {
return {
isSelected(id: string) {
return selectedItemIds.includes(id);
},
toggle(id: string) {
if (selectedItemIds.includes(id)) {
setSelectedItemIds(selectedItemIds.filter((i) => i !== id));
return;
}
setSelectedItemIds([...selectedItemIds, id]);
},
};
}, [selectedItems]);

return (
<Finder items={items} rules={rules} context={context}>
<Finder.Content>{{ items: IssueTrackerItems }}</Finder.Content>
</Finder>
);
}

Consume the context in the Item renderprop

The second generic of the FinderContentItemProps type is the Context. From here, you can use those contextual methods and props to your hearts content.

function IssueTrackerItems({ items, context }: FinderContentItemProps<Issue, IssueTrackerContext>) {
return items.map((item) => {
const isSelected = context.isSelected(item.id);
return (
<button type="button" data-is-selected={isSelected} onClick={() => context.toggle(item.id)} key={item.id}>
<input type="checkbox" checked={isSelected} readOnly={true} />
Severity {item.severity}: {item.subject} - {item.user_name}
</button>
);
});
}