# RAN012 Reactive read after the first await of an async memo

`warning RAN012`: *`userId.Value` is read after the first `let!`/`do!` of this async memo; a read after an await that
suspends is untracked, and a change to `userId` starts no flight.*

**Cause.** An async memo tracks the reads its body makes while it runs synchronously, up to the first await that
suspends. A read in a continuation is untracked, so a change to that source starts no flight. A `let!` on a task that
has already completed does not suspend; the rule reports it too. The rule follows an await in a bind's continuation and
after an `if`, loop or `try` whose body awaits, and a read anywhere in a loop whose body awaits runs after the previous
iteration's await. An await counts when it belongs to the memo's own computation. A read in the body of a memo, effect,
boundary or async value created after the await, or under `untrack`, is tracked by that body and is not reported; a read
in `createRoot`'s body, `createEffectOn`'s act or an `onCleanup` callback is.

**Fix.** Read the source before the first await and bind it to a local.

### Triggers

```fsharp
module Example

open System.Threading.Tasks
open Ranvier

let profile (userId: Signal<int>) =
    createAsync (fun _ _ ->
        task {
            do! Task.Yield ()
            return userId.Value
        })
```

### Fixed

```fsharp
module Example

open System.Threading.Tasks
open Ranvier

let profile (userId: Signal<int>) =
    createAsync (fun _ _ ->
        task {
            let id = userId.Value
            do! Task.Yield ()
            return id
        })
```

**Suppression.** `// fsharpanalyzer: ignore-line RAN012`, with the reason on the line before.
