diff --git a/.changeset/wet-cobras-happen.md b/.changeset/wet-cobras-happen.md deleted file mode 100644 index b472480e8..000000000 --- a/.changeset/wet-cobras-happen.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -"ember-resources": minor ---- - -`trackedFunction` can now be composed just like regular resources. - -The function body still auto-tracks and will update within consuming resource appropriately. - -
Example - -```ts -const Person = resourceFactory((maybeIdFn) => { - return resource(({ use }) => { - let request = use( - trackedFunction(async () => { - let id = typeof maybeIdFn === "function" ? maybeIdFn() : maybeIdFn; - let response = await fetch(`https://github.com/gitapi/users/${id}`); - return response.json(); - }) - ); - - // `use` returns a ReadonlyCell where `.current` - // is the State of trackedFunction. - return () => request.current; - }); -}); -``` - -Usage examples: - -```gjs - -``` - -
- -
An async doubler - -```ts -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(); -``` - -
- -
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). - -```ts -// 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 - ); - }, - }; - }); -}); -``` - -
diff --git a/ember-resources/CHANGELOG.md b/ember-resources/CHANGELOG.md index 71e388331..74b7cdbcf 100644 --- a/ember-resources/CHANGELOG.md +++ b/ember-resources/CHANGELOG.md @@ -1,5 +1,139 @@ # ember-resources +## 6.4.0 + +### Minor Changes + +- [#975](https://github.com/NullVoxPopuli/ember-resources/pull/975) [`1a964f1`](https://github.com/NullVoxPopuli/ember-resources/commit/1a964f16ca6e528c337ad2788d4c870aa699ef32) Thanks [@NullVoxPopuli](https://github.com/NullVoxPopuli)! - `trackedFunction` can now be composed just like regular resources. + + The function body still auto-tracks and will update within consuming resource appropriately. + +
Example + + ```ts + const Person = resourceFactory((maybeIdFn) => { + return resource(({ use }) => { + let request = use( + trackedFunction(async () => { + let id = typeof maybeIdFn === "function" ? maybeIdFn() : maybeIdFn; + let response = await fetch(`https://github.com/gitapi/users/${id}`); + return response.json(); + }) + ); + + // `use` returns a ReadonlyCell where `.current` + // is the State of trackedFunction. + return () => request.current; + }); + }); + ``` + + Usage examples: + + ```gjs + + ``` + +
+ +
An async doubler + + ```ts + 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(); + ``` + +
+ +
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). + + ```ts + // 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 + ); + }, + }; + }); + }); + ``` + +
+ ## 6.3.1 ### Patch Changes diff --git a/ember-resources/package.json b/ember-resources/package.json index 70aea2336..a2dd56e21 100644 --- a/ember-resources/package.json +++ b/ember-resources/package.json @@ -1,6 +1,6 @@ { "name": "ember-resources", - "version": "6.3.1", + "version": "6.4.0", "keywords": [ "ember-addon" ],