nenu-lang / page-effects-and-handlers
Stable

Page Effects And Handlers

  • Handlers are ordinary top-level typed functions.
  • Use one top-level on load block for initial page work.
  • Use on change with explicit state dependencies and avoid writing a dependency from its own effect.

Handlers Are Functions

A click, submit, or row event points to a top-level Nenu function. Keep the handler small and move reusable work into another function when several events or effects need it.

code
1fn clearDraft() {2  draft_title = ""3  draft_amount = 04  draft_note = ?5}67fn chooseExpense(Expense expense) {8  selected_expense = expense9}1011fn closeDetails() {12  selected_expense = ?13}

In repeated visual content, App Marché can supply the current row to a compatible typed parameter such as Expense expense. Bind the bare handler name; the visual event owns invocation and row context.

Initial Work With on load

code
1fn refreshExpenses() {2  loading = true3  result = ListExpensesApi({ room_id })4  expenses = result.expenses5  loading = false6}78on load() {9  refreshExpenses()10}
  • Use one top-level on load() block.
  • on load() takes no parameters.
  • Call an ordinary function when load behavior is also needed after a save or delete.
  • Keep function and effect declarations at Page Script top level.

Reactive Work With on change

on change names one or more existing state dependencies. Its body reruns when those dependencies change. Use it for derived page behavior that needs statements rather than a simple expression.

code
1Expense[] visible_expenses = []2Expense[] expenses = []3string query = ""4bool include_settled = false56on change(query, include_settled, expenses) {7  visible_expenses = expenses.filter(8    it.title.lowercase().contains(query.lowercase()) and9      (include_settled or it.status != ExpenseStatus.Settled)10  )11}
  • Dependencies are comma-separated identifiers.
  • Each dependency must already be a page-state binding.
  • The effect body contains statements, not nested functions or effects.
  • Prefer a normal function when the same operation is triggered manually and reactively.

Avoid Effect Cycles

code
1on change(query, expenses) {2  visible_expenses = expenses.filter(3    it.title.contains(query)4  )5}

The self-triggering version writes the same state it depends on. That creates a dependency cycle and is rejected. Normalize the value in the input handler or derive a separate state value instead.

Returning From A Handler

code
1bool fn canClose() {2  if saving {3    return false4  }56  return true7}

A callback contract may expect a return value. Use the same complete-return rules as any other function. Void event handlers simply finish without returning a value.

Common Mistakes

WrongCorrect
on load(room_id)on load() and read room_id from scope.
Nested on changeKeep effects at top level.
Write an effect dependency inside that effectWrite a separate derived state value.
Bind () => chooseExpense(row)Bind the bare compatible handler name.
Use throw for page feedbackUse state, control flow, and a toast.

Continue Learning