Skip to content

useDispatch Deprecated

Adds a dispatch helper function to emit custom events. Useful to communicate between different controllers.

WARNING

Deprecated: useDispatch() is deprecated. Please use the built-in this.dispatch() function from Stimulus: https://stimulus.hotwired.dev/reference/controllers#cross-controller-coordination-with-events

Migration guide

Because the dispatch() function from Stimulus is very similar, the migration process to the Stimulus version of dispatch() should be fairly simple:

  • remove the useDispatch import
  • remove the useDispatch initializer
  • wrap your payload in a detail object
js
  import { Controller } from '@hotwired/stimulus'
- import { useDispatch } from 'stimulus-use'

  export default class extends Controller {
    connect() {
-     useDispatch(this)
    }

    add() {
-     this.dispatch('add', { quantity: 1 })
+     this.dispatch('add', { detail: { quantity: 1 } })
    }
  }

Reference

Mixin

js
useDispatch(controller, options = {})

controller : a Stimulus Controller (usually 'this')

options :

OptionDescription           Default value               
elementThe element the event will be emitted from.The controller element
eventPrefixWhether to prefix or not the emitted event. Can be a boolean or a string.
- true prefix the event with the controller identifier item:add
- someString prefix the event with the given string someString:add
- false to remove prefix
true
bubblesWhether the event should bubble.true
cancelableWhether the event is cancelable.true
debugWhether to log debug information. See debug for more information on the debugging toolsfalse

The dispatch function

Once the useDispatch mixin is applied, your controller has a new this.dispatch function available you may use to emit custom events.

js
dispatch(eventName, detail = {})
ParamDescription
eventNamea mandatory string for the name of the event to emit.
detailA payload object that will be passed through the event and available for the receiver with event.detail

dispatch() returns the created CustomEvent, which you can use to inspect the event or check whether it was cancelled (for example via event.defaultPrevented).

Usage

js
// item_controller.js
import { Controller } from '@hotwired/stimulus'
import { useDispatch } from 'stimulus-use'

export default class extends Controller {
  connect() {
    useDispatch(this)
  }

  add() {
    // dispatch a custom event item:add
    this.dispatch("add")
  }
}

Bubbling events

The emitted event sent by the dispatch function will bubble up the tree of the DOM. Therefore all parent elements can listen to it directly.

html
<div data-controller="reciever" data-action="emitter:add->reciever#update">
  <div data-controller="emitter" data-action="click->emitter#add" ></div>
</div>

If both are at the same level or if the reciever controller is even nested within the controller, you should listen to event with @window to catch it.

html
<div data-controller="reciever" data-action="emitter:add@window->reciever#update"></div>
<div data-controller="emitter" data-action="click->emitter#add" ></div>

Example building a cart counter with the dispatch helper

The HTML markup. See the custom event item:add that the cart controller is listening to

html
<div data-controller="cart"
     data-action="item:add->cart#refreshTotal"
     data-cart-counter="0">

  <button data-controller="item" data-action="item#add">
    Add
  </button>

  <div>
    <span>No of items : </span>
    <span data-cart-target="counterView">0</span>
  </div>
</div>

The item controller dispatching the event

js
//item_controller.js
import { useDispatch } from 'stimulus-use'

export default class extends Controller {
  connect() {
    useDispatch(this)
  }

  add() {
    this.dispatch('add', { quantity: 1 })
  }
}

The cart controller receiving the event

js
//cart_controller.js
import { ApplicationController } from 'stimulus-use'

export default class extends ApplicationController {
  static targets = ['counterView']

  refreshTotal(e) {
    this.counter += e.detail.quantity
    console.log(e.detail.controller) // the emitting item_controller
  }

  renderCounter() {
    this.counterViewTarget.textContent = this.counter
  }

  set counter(value) {
    this.data.set('counter', value)
    this.renderCounter()
  }

  get counter() {
    return this.data.get('counter')
  }
}