diff --git a/apps/docs/markdown-pages/docs/manual/mutation.mdx b/apps/docs/markdown-pages/docs/manual/mutation.mdx index 67de71dfc..734771814 100644 --- a/apps/docs/markdown-pages/docs/manual/mutation.mdx +++ b/apps/docs/markdown-pages/docs/manual/mutation.mdx @@ -91,3 +91,22 @@ Note that the previous binding `five` stays `5`, since it got the underlying ite ## Tip & Tricks Before reaching for `ref`, know that you can achieve lightweight, local "mutations" through [overriding let bindings](./let-binding.mdx#binding-shadowing). + +### Self-Referencing Callbacks + +Sometimes a callback needs a value returned by the function that registers it. For example, suppose `subscribe` registers a message callback and returns a function that unsubscribes it. To unsubscribe after the first message, create a `ref` with a no-op function, then assign the returned function to it: + +```res +@val external subscribe: (string => unit) => unit => unit = "subscribe" + +let unsubscribe = ref(() => ()) + +unsubscribe := subscribe(message => { + Console.log(message) + unsubscribe.contents() +}) +``` + +The callback reads `unsubscribe.contents` when a message arrives, so it sees the function assigned after `subscribe` returns. + +This assumes `subscribe` delivers messages after it returns. A callback invoked during subscription would still call the initial no-op function.