Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release Preview #979

Merged
merged 1 commit into from
Aug 8, 2023
Merged

Release Preview #979

merged 1 commit into from
Aug 8, 2023

Conversation

github-actions[bot]
Copy link
Contributor

@github-actions github-actions bot commented Aug 8, 2023

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

[email protected]

Minor Changes

  • #975 1a964f1 Thanks @NullVoxPopuli! - trackedFunction can now be composed just like regular resources.

    The function body still auto-tracks and will update within consuming resource appropriately.

    Example
    const Person = resourceFactory((maybeIdFn) => {
      return resource(({ use }) => {
        let request = use(
          trackedFunction(async () => {
            let id = typeof maybeIdFn === "function" ? maybeIdFn() : maybeIdFn;
            let response = await fetch(`https://api.github.com/users/${id}`);
            return response.json();
          })
        );
    
        // `use` returns a ReadonlyCell where `.current`
        // is the State of trackedFunction.
        return () => request.current;
      });
    });

    Usage examples:

    <template>
        {{#let (Person 1) as |request|}}
          {{#if request.isLoading}}
             ... loading ...
          {{/if}}
    
          {{#if request.value}}
    
          {{/if}}
        {{/let}}
    </template>
    An async doubler
    const Doubled = resourceFactory((num: number) => {
      return resource(({ use }) => {
        let doubler = use(trackedFunction(async () => num * 2));
    
        // Since current is the "State" of `trackedFunction`,
        // accessing .value on it means that the overall value of
        // `Doubled` is the eventual return value of the `trackedFunction`
        return () => doubler.current.value;
      });
    });
    
    // Actual code from a test
    class State {
      @tracked num = 2;
    }
    
    let state = new State();
    
    setOwner(state, this.owner);
    
    await render(<template><out>{{Doubled state.num}}</out></template>);
    Example with arguments

    Imagine you want to compute the hypotenuse of a triangle,
    but all calculations are asynchronous (maybe the measurements exist on external APIs or something).

    // Actual code from a test
    type NumberThunk = () => number;
    
    const Sqrt = resourceFactory((numFn: NumberThunk) =>
      trackedFunction(async () => {
        let num = numFn();
    
        return Math.sqrt(num);
      })
    );
    
    const Squared = resourceFactory((numFn: NumberThunk) =>
      trackedFunction(async () => {
        let num = numFn();
    
        return Math.pow(num, 2);
      })
    );
    
    const Hypotenuse = resourceFactory((aFn: NumberThunk, bFn: NumberThunk) => {
      return resource(({ use }) => {
        const aSquared = use(Squared(aFn));
        const bSquared = use(Squared(bFn));
        const c = use(
          Sqrt(() => {
            return (aSquared.current.value ?? 0) + (bSquared.current.value ?? 0);
          })
        );
    
        // We use the function return because we want this property chain
        // to be what's lazily evaluated -- in this example, since
        // we want to return the hypotenuse, we don't (atm)
        // care about loading / error state, etc.
        // In real apps, you might care about loading state though!
        return () => c.current.value;
    
        // In situations where you care about forwarding other states,
        // you could do this
        return {
          get value() {
            return c.current.value;
          },
          get isLoading() {
            return (
              a.current.isLoading || b.current.isLoading || c.current.isLoading
            );
          },
        };
      });
    });

@stackblitz
Copy link

stackblitz bot commented Aug 8, 2023

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@NullVoxPopuli NullVoxPopuli merged commit ae1e239 into main Aug 8, 2023
1 check passed
@NullVoxPopuli NullVoxPopuli deleted the changeset-release/main branch August 8, 2023 18:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant