Xstate: [Question] Using "external deps" in guards

Created on 17 Jul 2019  路  3Comments  路  Source: davidkpiano/xstate

Is it ok to use "external deps" in guards?

E.g.

{
  guards: {
    hasAccessToken: (ctx, event) =>
      ctx.foo && event.bar && !!localStorage.getItem("token")
  }
}
documentation question

Most helpful comment

Keep in mind that this simplified solution might fall short when a localStorage value can get changed by another browser tab.

If this is irrelevant for the particular problem I would of course also put it into machine's initial context.

All 3 comments

IMHO it's OK - while it's maybe not ideal I usually try to apply "don't overcomplicate things" strategy. Without this you'd have to somehow check externally for localStorage changes and send events to the machine which in turn would update its context. While this is not impossible I believe the return of such investment is not worth it in majority of cases.

This will "work" but when it comes to testing, analysis, simulation, you might have problems. In general, guards should be pure and this function is 馃毇 not pure 馃毇.

So how can we make it pure? Use context.

const machine = Machine({
  // ...
  context: {
    token: null
  },
  // ...
}, {
  guards: {
    hasAccessToken: ctx => !!ctx.token
  }
});

const machineWithToken = machine.withConfig({ token: localStorage.get('token') });

Now it can be modeled in a more flexible, testable way.

Keep in mind that this simplified solution might fall short when a localStorage value can get changed by another browser tab.

If this is irrelevant for the particular problem I would of course also put it into machine's initial context.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

amelon picture amelon  路  3Comments

suku-h picture suku-h  路  3Comments

mattiamanzati picture mattiamanzati  路  3Comments

bradwoods picture bradwoods  路  3Comments

carloslfu picture carloslfu  路  3Comments