Function trackedFunction

  • Any tracked data accessed in a tracked function before an await will "entangle" with the function -- we can call these accessed tracked properties, the "tracked prelude". If any properties within the tracked payload change, the function will re-run.

    import Component from '@glimmer/component';
    import { tracked } from '@glimmer/tracking';
    import { resourceFactory, resource, use } from 'ember-resources';
    import { trackedFunction } from 'reactiveweb/function';
    import { on } from '@ember/modifier';

    function Request(idFn) {
    return resource(({use}) => {
    let trackedRequest = use(trackedFunction(async () => {
    let id = idFn();
    let response = await fetch(`https://swapi.dev/api/people/${id}`);
    let data = await response.json();

    return data; // { name: 'Luke Skywalker', ... }
    }));

    return trackedRequest;
    });
    }

    class Demo extends Component {
    @tracked id = 1;

    updateId = (event) => this.id = event.target.value;

    request = use(this, Request(() => this.id));

    // Renders "Luke Skywalker"
    <template>
    {{this.request.current.value.name}}

    <input value={{this.id}} {{on 'input' this.updateId}}>
    </template>
    }

    Type Parameters

    • Return

    Parameters

    Returns State<Return>

  • Any tracked data accessed in a tracked function before an await will "entangle" with the function -- we can call these accessed tracked properties, the "tracked prelude". If any properties within the tracked payload change, the function will re-run.

    import Component from '@glimmer/component';
    import { tracked } from '@glimmer/tracking';
    import { trackedFunction } from 'reactiveweb/function';

    class Demo extends Component {
    @tracked id = 1;

    request = trackedFunction(this, async () => {
    let response = await fetch(`https://swapi.dev/api/people/${this.id}`);
    let data = await response.json();

    return data; // { name: 'Luke Skywalker', ... }
    });

    updateId = (event) => this.id = event.target.value;

    // Renders "Luke Skywalker"
    <template>
    {{this.request.value.name}}

    <input value={{this.id}} {{on 'input' this.updateId}}>
    </template>
    }

    Note, this example uses the proposed <template> syntax from the First-Class Component Templates RFC

    Also note that after an await, the this context should not be accessed as it could lead to destruction/timing issues.

    Type Parameters

    • Return

    Parameters

    • context: object

      destroyable parent, e.g.: component instance aka "this"

    • fn: (() => Return)

      the function to run with the return value available on .value

    Returns State<Return>