Blazor Component Lifecycle Events
Introduction
Blazor components follow a well-defined lifecycle from creation to disposal. Understanding these lifecycle events is crucial for building efficient, performant, and maintainable Blazor applications. In this article, we'll explore each lifecycle event, understand when to use them, and examine practical examples.
What Are Lifecycle Events?
Lifecycle events are methods that Blazor automatically calls at specific points during a component's existence. They provide hooks where you can execute custom code, such as:
- Loading data from APIs or databases
- Initializing component state
- Performing JavaScript interop
- Optimizing rendering performance
- Cleaning up resources
Most lifecycle events come in two versions: synchronous and asynchronous, allowing you to choose the appropriate version based on your needs.
The Component Lifecycle Flow
When a Blazor component is created and rendered, the lifecycle events execute in the following order:
- Constructor (standard C# constructor)
- OnInitialized()
- OnInitializedAsync()
- OnParametersSet()
- OnParametersSetAsync()
- ShouldRender() (if the component needs to render)
- OnAfterRender(firstRender)
- OnAfterRenderAsync(firstRender)
When a component's state or parameters change, steps 4-8 repeat.
Lifecycle Events in Detail
1. OnInitialized and OnInitializedAsync
When they run: Once, when the component is first initialized.
Use cases:
- Loading initial data
- Setting up component state
- Initializing services
Key points:
- These methods run only once during the component's lifetime
OnInitialized()runs first, thenOnInitializedAsync()- The UI has not been rendered yet when these execute
- Use the async version for long-running operations like API calls
Example:
Common mistake: Trying to reload data in OnInitialized() when a parameter changes. Since this method only runs once, parameter changes won't trigger a data reload. Use OnParametersSet() instead.
2. OnParametersSet and OnParametersSetAsync
When they run:
- After
OnInitialized()methods (during initial load) - Every time a parameter value changes
Use cases:
- Reloading data when parameters change
- Validating parameter values
- Deriving state from parameters
Key points:
- These methods run on both initialization and parameter changes
- Perfect for components that need to update based on parameter values
- If you load data here, it will reload every time parameters change
Example:
Best practice: If your data loading depends on parameter values, use OnParametersSetAsync() instead of OnInitializedAsync() to ensure data refreshes when parameters change.
3. OnAfterRender and OnAfterRenderAsync
When they run: After the component has finished rendering.
Use cases:
- JavaScript interop (required when prerendering is enabled)
- DOM manipulation
- Setting focus on elements
- Initializing JavaScript libraries
Key points:
- All HTML elements are rendered and available in the DOM
- The
firstRenderparameter indicates if this is the component's first render - Use
firstRenderto run code only once after the initial render - This is the only safe place for JavaScript interop when prerendering is enabled
Example:
Important: If you disable prerendering, you can call JavaScript in other lifecycle methods, but it's still a best practice to use OnAfterRender methods to ensure the DOM is ready.
4. ShouldRender
When it runs: Before the component re-renders (after state changes).
Use cases:
- Performance optimization
- Preventing unnecessary re-renders
- Conditional rendering logic
Key points:
- Return
falseto skip rendering - The component always renders at least once, even if this returns
false - Does not have an async version
- Use sparingly and only when you have measured performance issues
Example:
Warning: Overusing ShouldRender() can lead to bugs where the UI doesn't update when it should. Only use it for measured performance optimizations.
Practical Examples
Example 1: Loading Data with Parameters
Example 2: JavaScript Interop with Focus Management
Example 3: Performance Optimization with ShouldRender
Common Patterns and Best Practices
1. Async vs. Sync: Which to Choose?
- Use async versions for I/O operations (API calls, database queries, file operations)
- Use sync versions for quick, in-memory operations
- Don't use async methods if you're not doing async work
2. OnInitialized vs. OnParametersSet
- Use
OnInitialized()for data that doesn't depend on parameters - Use
OnParametersSet()for data that depends on parameter values - Remember:
OnParametersSet()runs on every parameter change, so cache data if needed
3. Managing State Updates
4. Cancellation Token Support
Always support cancellation in long-running async operations:
Common Mistakes to Avoid
❌ Don't: Call JavaScript in OnInitialized
✅ Do: Call JavaScript in OnAfterRender
❌ Don't: Forget to Check firstRender
✅ Do: Use firstRender Parameter
❌ Don't: Load Parameter-Dependent Data in OnInitialized
✅ Do: Load Parameter-Dependent Data in OnParametersSet
Performance Considerations
1. Minimize Re-renders
- Use
ShouldRender()judiciously for expensive components - Avoid unnecessary state changes
- Use
@keydirective to help Blazor track component identity
2. Async Operation Management
- Always use
CancellationTokenfor async operations - Dispose of resources properly
- Avoid sync-over-async patterns
3. Data Loading Strategies
Testing Lifecycle Events
When unit testing components with lifecycle events:
Conclusion
Understanding Blazor component lifecycle events is essential for building robust, efficient applications. Here are the key takeaways:
- OnInitialized/Async - Use for one-time initialization and data loading
- OnParametersSet/Async - Use when data depends on component parameters
- OnAfterRender/Async - Use for JavaScript interop and DOM manipulation
- ShouldRender - Use sparingly for performance optimization