RizzyUI

Debugging and Best Practices

You've learned the patterns for building powerful, interactive components with RizzyUI and Alpine.js. Now, let's talk about what to do when things don't work as expected. Debugging client-side interactivity can be tricky, but with the right tools and knowledge of common pitfalls, you can solve issues quickly.

Essential Debugging Tools

1. The Alpine.js DevTools Extension

This is your most powerful tool. The Alpine.js DevTools is a browser extension (available for Chrome and Firefox) that lets you inspect the state of all your Alpine components on the page.

  • Inspect State: See the current values of all properties in your x-data objects in real-time.
  • Modify State: Change data directly in the devtools panel to see how your component reacts.
  • Component Tree: View a tree of all initialized Alpine components on the page.

2. Good Old console.log()

When you need to see what's happening at a specific moment, console.log() is your best friend. You can log the entire component instance (this) or its data context (this.$data) to inspect its properties and methods.

Source
export default () => ({
  count: 0,
  
  increment() {
    this.count++;
    // Log the entire component's data context
    console.log(this.$data); 
  }
});

3. Alpine.raw() for Clean Logging

When you console.log an Alpine data object, you'll see a lot of Proxy information. To see the raw, underlying data without the reactivity wrappers, use Alpine.raw().

Source
// Inside a method
console.log(Alpine.raw(this.myComplexObject));

Common Pitfalls and How to Fix Them

1. CSP Error: "Refused to execute inline script..."

  • Cause: You are using the rizzyui-csp.js build and have an inline JavaScript expression in your markup (e.g., x-on:click="isOpen = !isOpen").
  • Fix: Move the logic into a method in your .razor.js file and call it by name (e.g., x-on:click="toggle").

2. `AsChild` Error: A Button Inside a Button

  • Cause: You placed an <RzButton> inside a component that also renders a button, like <SheetTrigger>, without the `AsChild` property.
  • Fix: Add AsChild to the parent RizzyUI component (e.g., <SheetTrigger AsChild>). This tells it to merge its behavior into your button instead of rendering its own.

3. Timing Issue: `$refs` is `undefined` in `init()`

  • Cause: The init() method runs before Alpine has necessarily rendered conditional elements (like those inside an x-if or x-show).
  • Fix: Wrap your logic in this.$nextTick(() => { ... }). This tells Alpine to wait until the next DOM update cycle before running your code.

4. Case Sensitivity with `Props`

  • Cause: C# uses PascalCase by default, but JSON serialization and JavaScript convention use camelCase.
  • Fix: Always access your props in JavaScript using camelCase. MyMessage in C# becomes myMessage in your .razor.js file.

5. HTMX and Stale References

  • Cause: The target component's DOM element was replaced by an HTMX swap, and your stored reference to its Alpine instance is now stale.
  • Fix: Re-acquire the reference to the component inside the method that performs the action, right before you use it.

Best Practices for Performance and Maintainability

  • Keep `x-data` Lean: Only include properties that are truly reactive. Avoid storing large, static objects in your component's state if they don't need to trigger UI updates.
  • Prefer `x-show` over `x-if`: Use x-show for elements that are toggled frequently. Use x-if only when you need to completely remove an element from the DOM.
  • Clean Up in `destroy()`: Always clean up manual event listeners, timers, or third-party libraries in the destroy() method to prevent memory leaks, especially in applications that use HTMX.
  • Use Co-located Files: For any logic more complex than a simple toggle, use the Alpine Code-Behind pattern. It keeps your markup clean and your logic organized.

Conclusion

You've now covered the entire lifecycle of building interactive components in RizzyUI, from the fundamentals to advanced orchestration and debugging. You have a powerful set of tools to create rich, server-driven applications with just the right amount of client-side magic.

With this foundation, you're ready to explore the RizzyUI component library and apply these patterns to build your own amazing user experiences. Happy coding!