Feature request / query
I have a piece of UI that I'd like to display when one of multiple states is true. At the moment, I'm writing code like this:
const displayCustomerBalance = current.matches("customer_deposit") || current.matches("customer_withdrawal");
This is okay, but gets a bit cumbersome when you add more states. It would be nice to be able to write something more like:
const displayCustomerBalance = current.matches([
"customer_deposit",
"customer_withdrawal"
]);
It might be that you can actually do something like this and I've missed or misunderstood something. If so, sorry!
I think adding an overload for State.matches() with a signature like this would work, where TSV is a union of the possible value types instead of a single value type:
matches<TSV>(parentStateValues: TSV[]): this is TState extends { value: TSV; } ? State<TState["context"], TEvent, TStateSchema, TState> : never
It would call utils.ts/matchesState for each of the state values passed in, and return true if any of them were true.
This can be easily added in userland as a custom helper, not sure if it's worth overloading a core feature with this complexity.
That's fair enough. My main argument in favour of the change would be that, because it's such a core feature, it makes sense to prioritise ergonomics. The pattern of providing either a single value or an array exists elsewhere in the library (when defining actions on a state transition, for example), so I assumed it would work on matches() and was surprised when it didn't.
As an aside, the array form doesn't currently produce a TypeScript error or throw an exception, it just returns false. Are there cases when a state value can actually be an array, or is this a bug?
Are there cases when a state value can actually be an array, or is this a bug?
There are not - it's always object and/or string.
I'll add this as an enhancement to V5, which will be much more modular, so adding this helper will not be included in the bundle.
Sounds good to me!
const isMatch = ["customer_deposit", "customer_withdrawal"].some(current.matches)
Would that work?
I have made the following helper function that seems to work well.
export const matchesMachineState = (
states: string[],
machine: State<any, any, any, any>
) => (states.find((state) => machine.matches(state)) ? true : false);
Most helpful comment
Would that work?