Share Data between Riot Components with Mitt (event emitter)

Share Data between Riot Components with Mitt (event emitter)

This article covers using Events with Mitt between multiple Riot components for sharing data.

Before starting, make sure you have a base application running, or read my previous article Setup Riot + BeerCSS + Vite.

These articles form a series focusing on RiotJS paired with BeerCSS, designed to guide you through creating components and mastering best practices for building production-ready applications. I assume you have a foundational understanding of Riot; however, feel free to refer to the documentation if needed: https://riot.js.org/documentation/

It exist 3 methods for sharing data between components:

Use Riot properties (props) to pass values to a child component. The child component must emit Events to the parent component if an action happens, such as a click or input change. In this case, the communication scope is limited: parent component to child and child to parent.
Use a state manager: it allows you to share a state across components/pages, such as Pinia for Vuejs, or Redux for React. The communication scope is global: All components can view and edit states.
Use a Pub/Sub Event Emitter like Mitt: It is a messaging pattern to send data, the publisher emits the data, and the listener handles the data without without knowledge of which publishers.

Stepper Component Base

Example of dialog component made with RiotJS to emit Event to a listener.

/** EVENT BUS **/
import mitt from mitt

const _bus = mitt();

export default _bus;

<c-dialog>
<dialog class=
{state.active ? ‘active ‘ : null}
{props?.blur ? ‘overlay blur ‘ : null}
{props?.left ? ‘left ‘ : null}
{props?.right ? ‘right ‘ : null}
{props?.top ? ‘top ‘ : null}
{props?.bottom ? ‘bottom ‘ : null}
{props?.max ? ‘max ‘ : null}

>
<h5>{ state.title }</h5>
<div>
{ state.message }
</div>
<nav class=“right-align no-space”>
<button onclick={ toggleModal } class=“transparent link”>{ state.cancel }</button>
<button onclick={ validateAction } class=“transparent link”>{ state.validate }</button>
</nav>
</dialog>
<script>
import events from ./events.js

export default {
state: {
active: false,
title: Confirmation,
message: Are you sure?,
callbackID : ,
args : true,
validate : Validate,
cancel: Cancel
},
onMounted() {
events.on(open-modal-validation, this.openModalValidation);
},
onUnmounted() {
events.off(open-modal-validation, this.openModalValidation);
},
validateAction () {
if (this.state.callbackID) {
events.emit(this.state.callbackID, this?.state?.args);
}
this.toggleModal();
},
openModalValidation ({ message, callbackID, args }) {
this.update({
message,
callbackID,
args: args ?? true
})
this.toggleModal();
},
toggleModal() {
this.update({ active: !this.state.active })
if (this.state.active === true) {
console.log(Modal opened.)
} else {
console.log(Modal closed.)
}
}
}
</script>
</c-dialog>

<index-riot>
<div style=“width:600px;padding:20px;”>
<c-dialog />
<c-button onclick={ confirmDeletion }> Delete File </c-button>
</div>
<script>
import cButton from ../../components/c-button.riot;
import cSnackbar from ../../components/c-snackbar.riot;
import cDialog from ./c-dialog.riot;

import events from ./events.js

export default {
components: {
cButton,
cDialog
},
onMounted() {
events.on(delete-file, this.deleteFile);
},
onUnmounted() {
events.off(delete-file, this.deleteFile);
},
state: {
active: false
},
confirmDeletion () {
events.emit(open-modal-validation, {
message: Do you confirm you want to delete the file 2024-04-invoice.pdf?,
callbackID: delete-file
});
},
deleteFile () {
console.log(FILE DELETED! 🗑️);
}
}
</script>
</index-riot>

Leave a Reply

Your email address will not be published. Required fields are marked *