Share functions between Liveview JS Hooks

I was wondering if it’s possible to re-use a JS function on different liveview js hooks.
In the documentation I see that each hook is a separate JS object.
In other words : Can JS hooks share JS functions?

As I understand it a hook simply invokes whatever code you specify, so this should work.

import YourHook from "./js/hook";

const Hooks = {
  HookA: YourHook,
  HookB: YourHook
};

let liveSocket = new LiveSocket("/live", Socket, {
  params: { _csrf_token: csrfToken },
  hooks: Hooks,
});

You can now use phx-hook=“HookA” or phx-hook=“HookB” and they’d use the same underlying hook code. That said, if you want to reuse it, why not just use the same hook in multiple places?

Thanks, but I don’t want to reuse the whole hook.
Actually, my question is if you one can SHARE functions between hooks.

for example :

HookA = {
mounted() {
this.function1();
this.function2();
},
function1() {
// some code here
},
function2() {
// some more code here
}
}

HookB = {
mounted() {
// How to refer to function1() of **HookA** ??
}

Would it be possible to extract the functions outside of the hook and pass the hook as an argument to get access to the state?

function function1(hook) {
  hook.el.innerText = "hello from function1"
}

const HookA = {
  mounted() {
    function1(this)
  }
}

const HookB = {
  mounted() {
    function1(this)
  }
}

I don’t understand the problem/question you want to call function of another hook. Do you mean you want to change state (data) in hook A from hook B? Because original post only talked about reusing functions? Could explain clearly what you want to do in detail because answer you gave to dredison conflicts with your original question?

Thanks!
The “this” keyword was the missing piece for me.
With your proposed solution my code works and can create reusable functions between my hooks.

:grinning:

That works, but the more idiomatic way in javascript is to rebind this:

function function1() {
  this.el.innerText = "hello from function1"
}

const HookA = {
  mounted() {
    function1.call(this)
  }
}

const HookB = {
  mounted() {
    function1.call(this)
  }
}
1 Like

Thanks, I didn’t know that.

Would it be possible to use JSDoc to annotate function1’s this as a hook? Seems so, but docs show @this in popups.

That gives auto-completion and basic type checks in VSCode out of the box:

/ **
  * @this import("phoenix_live_view").ViewHook
  */
function function1() {
  this.el.innerText = "hello from function1"
}

const HookA = {
  mounted() {
    function1.call(this)
  }
}

const HookB = {
  mounted() {
    function1.call(this)
  }
}

Not sure if I prefer this approach over passing hooks explicitly.