Some basic knowledge of reactive UIs and state management is recommended.
What is $ui.register?
You can interact with the user interface via APIs provided to your plugin when you register a UI context.
function init() {
// This function registers the UI context for your plugin, allowing it to
// have access to UI APIs
$ui.register((ctx) => {
// ctx contains all the APIs
})
}
Unlike hooks which are called every time a specific event is triggered, the function inside $ui.register is called only once during the lifetime of your plugin, right after init(), in other words, each time your plugin is loaded.
You cannot register hook handlers inside the UI callback.
Fetch
In the UI context, 'ctx.fetch' should be used instead of 'fetch' in order to avoid crashes caused by concurrency issues.
$ui.register(async (ctx) => {
const res = await ctx.fetch("https://jsonplaceholder.typicode.com/todos/1")
const data = res.json()
})
States
State management allows you to keep track of dynamic data within your plugin. This approach not only helps maintain a clear separation of concerns but also enables reactive programming, where UI components like the Tray automatically update in response to changes in states.
//...
const count = ctx.state(0)
ctx.setInterval(() => {
count.set(c => c+1)
}, 1000)
function resetCount() {
count.set(0)
}
// Tray will update each time count changes
tray.render(() => tray.text(`Count: ${count.get()}`))
Effects
// Effect registers a callback that runs each time count changes
ctx.effect(() => {
console.log("count changed, " + count.get())
}, [count])
Example
Example
const currentMediaId = ctx.state<number | null>(null)
const fetchedData = ctx.state([])
// When the user navigates to an anime, get the media ID
ctx.screen.onNavigate((e) => {
if (e.pathname === "/entry" && !!e.searchParams.id) {
const id = parseInt(e.searchParams.id);
currentMediaId.set(id);
} else {
currentMediaId.set(null);
}
});
// Fetch data each time the media ID changes.
ctx.effect(async () => {
if (!currentMediaId.get()) return
const res = ctx.fetch(`https://example.com/anilistId?=${currentMediaId.get()}`)
// Store the results
fetchedData.set(res.json())
}, [currentMediaId])