Skip to main content

Dependent Rules

User story: Lindsay McUser wants to buy in-game food to feed their virtual pets, but they only have a limited amount of coins.

Hello Lindsay, you have $7.
$0$20
$2
$1
$3
$6
$3
$1
$2
$4
$4
$2
$8
$8
$7
$7
$10
$8
$7
$10
$8
$8
Assets from https://mohammed-23446.itch.io/32-16x16-food-sprites

Define the context shape

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

interface PetFoodStoreContext {
numCoins: number;
}

Define our context-aware ruleset

We're going to group the items into two categories, based on if the user can afford them.

The second generic of groupByRule is the Context shape, and the groupFn predicate will be passed the context object at runtime.

const rule = groupByRule<Food, PetFoodStoreContext>({
id: "can_afford",
groupFn: (item, context) => {
const canAfford = item.price < context.numCoins;
return canAfford ? "Can purchase" : "Too expensive";
},
sticky: {
header: "Can purchase",
},
}),
});
tip

Rules are re-hydrated whenever the items array or context reference is changed, so the groupFn will always receive the current context value.

Memoize context reference

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

function PetFoodStore() {
const [numCoins, setNumCoins] = useState<number>(7);
const context: PetFoodStoreContext = useMemo(() => {
return {
numCoins,
};
}, [numCoins]);
return (
<Finder items={items} rules={rules} context={context} requireGroup={true}>
<Finder.Content>
{{
groups: PetFoodStoreGroups,
}}
</Finder.Content>
</div>
</Finder>
);
}

For this example we're using a groupByRule, but all rules are passed the context reference.