xstate icon indicating copy to clipboard operation
xstate copied to clipboard

`state.matches` support for custom state IDs

Open daveyarwood opened this issue 2 years ago • 3 comments

Description

I'm really enjoying custom state IDs, as my state hierarchy is very nested. They work great for the target: "#some_specific_state" use case.

I was expecting state.matches("#some_specific_state") to work, too, but it always returns false even if the machine is in that state.

I tested this by doing some console.log debugging inside of a custom guard:

      guards: {
        templatesNotLoading: (_ctx, _e, { state }) => {
          console.log(`checking state: ${JSON.stringify(state)}`);
          console.log(`matches? ${state.matches("#templates_loading")}`);
          console.log(`matches!!? ${state.matches(
            "form_open.catalog_and_template_selection.template_selection.data_not_loaded.loading"
          )}`);

          return !state.matches("#templates_loading");
        }
      },

I confirmed that I do have the custom ID defined correctly on the relevant node:

                        loading: {
                          id: "templates_loading",
                          ...
                        }

Expected result

In the example above, I expect both console.logs to print true when the machine is in the templates loading state.

Actual result

The one with the absolute path prints true, but the one with the custom ID reference prints false.

Reproduction

Not readily available at the moment

Additional context

I'm using XState 4.32.1.

daveyarwood avatar Aug 02 '22 13:08 daveyarwood

This would be more of a feature than a bug. You can do this manually now:

function matchesId(state, id) {
  return !!state.configuration.find(stateNode => stateNode.id === id.slice(1));
}

matchesId(state, '#templates_loading'); // true or false

davidkpiano avatar Aug 02 '22 19:08 davidkpiano

Agreed -- this would be a nice to-have.

I like your helper function - I'll give that a try!

daveyarwood avatar Aug 02 '22 20:08 daveyarwood

Works like a charm :100:

daveyarwood avatar Aug 02 '22 20:08 daveyarwood

Closing this as it has a sensible workaround, and we likely don't want to introduce an additional helper function for this.

We may reconsider if it is a more common use-case that is desired for state.matches(...).

Also, note that tags can also be a feasible approach:

loading: {
  id: 'templates_loading',
  tags: ['loading']
}

// ...
state.hasTag('loading'); // true or false

davidkpiano avatar Jan 28 '23 23:01 davidkpiano