Class Resource<Args>

The 'Resource' base class has only one lifecycle hook, modify, which is called during instantiation of the resource as well as on every update of any of any consumed args.

Typically, a Resource will be used to build higher-level APIs that you'd then use in your apps. For example, maybe you want to build a reactive-wrapper around a non-reactive wrapper, XState which requires that the "State machine interpreter" is stopped when you are discarding the parent context (such as a component).

An example

import { Resource } from 'ember-resources';
import { createMachine, interpret } from 'xstate';

const machine = createMachine(); // ... see XState docs for this function this ...

class MyResource extends Resource {
@tracked customState;

constructor(owner) {
super(owner);

registerDestructor(this, () => this.interpreter.stop());
}

modify(positional, named) {
if (!this.interpreter) {
// Initial Setup
this.interpreter = interpret(machine).onTransition(state => this.customState = state);
} else {
// Subsequent Updates
this.interpreter.send('SOME_EVENT', { positional, named });
}
}
}

Once defined, there are two ways to use MyResource

  • in a template
  • in JavaScript

In the template, the Resource can be imported (or re-exported from the helpers directory)

When imported (using RFC 779),

import { MyResource } from './somewhere';

<template>
{{#let (MyResource) as |myResource|}}
{{log myResource.customState}}
{{/let}}
</template>

When using in javascript, you'll need the from utility

import { MyResource } from './somewhere';

class ContainingClass {
state = MyResource.from(this, () => [...])
}

However, when authoring a Resource, it's useful to co-locate an export of a helper function:

export function myResource(destroyable, options) {
return MyResource.from(destroyable, () => ({
foo: () => options.foo,
bar: () => options.bar,
}))
}

This way, consumers only need one import.

Type Parameters

  • Args = unknown

Hierarchy

Constructors

Methods

Constructors

  • new Resource<Args>(owner: unknown): Resource<Args>
  • Type Parameters

    • Args = unknown

    Parameters

    • owner: unknown

    Returns Resource<Args>

Methods

  • modify(positional: Positional<Args>, named: Named<Args>): void
  • this lifecycle hook is called whenever arguments to the resource change. This can be useful for calling functions, comparing previous values, etc.

    Parameters

    • positional: Positional<Args>
    • named: Named<Args>

    Returns void

  • from<SomeResource>(this: Constructor<SomeResource>, thunk: AsThunk<ArgsFrom<SomeResource>, ThunkReturnFor<ArgsFrom<SomeResource>>>): SomeResource
  • from<SomeResource>(this: Constructor<SomeResource>, context: unknown, thunk: AsThunk<ArgsFrom<SomeResource>, ThunkReturnFor<ArgsFrom<SomeResource>>>): SomeResource
  • For use in the body of a class.

    from is what allows resources to be used in JS, they hide the reactivity APIs from the consumer so that the surface API is smaller.

    import { Resource, use } from 'ember-resources';

    class SomeResource extends Resource {}

    class MyClass {
    @use data = SomeResource.from(() => [ ... ]);
    }

    Type Parameters

    • SomeResource extends Resource<any, SomeResource>

    Parameters

    • this: Constructor<SomeResource>
    • thunk: AsThunk<ArgsFrom<SomeResource>, ThunkReturnFor<ArgsFrom<SomeResource>>>

    Returns SomeResource

  • For use in the body of a class.

    from is what allows resources to be used in JS, they hide the reactivity APIs from the consumer so that the surface API is smaller. Though it may be more convenient to not wrap your resource abstraction in a helper function.

    import { Resource } from 'ember-resources';

    class SomeResource extends Resource {}

    class MyClass {
    data = SomeResource.from(this, () => [ ... ]);
    }

    However, if you have argument defaults or need to change the shape of arguments depending on what ergonomics you want your users to have, a wrapper function may be better.

    export function someResource(context, { foo, bar }) {
    return SomeResource.from(context, () => ... );
    }

    usage:

    import { someResource } from 'your-library';

    class SomeResource extends Resource {}

    class MyClass {
    @tracked foo;
    @tracked bar;

    data = someResource(this, {
    foo: () => this.foo,
    bar: () => this.bar
    });
    }

    Type Parameters

    • SomeResource extends Resource<any, SomeResource>

    Parameters

    • this: Constructor<SomeResource>
    • context: unknown
    • thunk: AsThunk<ArgsFrom<SomeResource>, ThunkReturnFor<ArgsFrom<SomeResource>>>

    Returns SomeResource

Generated using TypeDoc