Using refreshApex in LWC for Dynamic Data Refresh
When working with Lightning Web Components (LWC), you might want to refresh the data displayed in your component after performing CRUD (Create, Read, Update, Delete) operations. Suppose you are fetching data using an @wire decorator that calls an Apex method. You then process the retrieved data in your component, and you want this data to update dynamically after a user performs an action, such as creating a record. This can be achieved using the refreshApex function provided by Salesforce. However, it needs to be used correctly to avoid errors like “refresh failed because configuration is not available.”
Here’s an example scenario:
You have a wire service calling an Apex method:
@wire(getTodos, { searchKey: '$searchString' })
sendForSplitting({ error, data }) {
if (error) {
this.error = error;
} else if (data) {
this.splitTodos(data);
}
}This Apex method fetches a list of tasks and passes the data to the splitTodos method, which categorizes them into complete and incomplete tasks. After performing a CRUD operation (e.g., creating a new task), you want to refresh the dataset to reflect the updated data in the component.
Correct Usage of refreshApex
The refreshApex function works by refreshing the response of a wired property or function. To use it effectively:
- Store the wired result in a property using a variable.
- Call
refreshApexwith the stored wired result after the CRUD operation.
Here’s a revised implementation:
import { LightningElement, wire, track } from 'lwc';
import getTodos from '@salesforce/apex/TodoController.getTodos';
import createTodo from '@salesforce/apex/TodoController.createTodo';
import { refreshApex } from '@salesforce/apex';
export default class TodoList extends LightningElement {
@track searchString = '';
@track todos = [];
@track error;
wiredTodos; // To store the wired result
@wire(getTodos, { searchKey: '$searchString' })
wiredGetTodos(result) {
this.wiredTodos = result; // Store the wired result
const { data, error } = result;
if (data) {
this.splitTodos(data); // Process the data
} else if (error) {
this.error = error;
}
}
splitTodos(data) {
// Logic to categorize todos into complete and incomplete
this.todos = data;
}
handleCreate() {
createTodo({ taskName: 'New Task' })
.then(() => {
// Refresh the wire service after the record is created
return refreshApex(this.wiredTodos);
})
.catch((error) => {
console.error('Error creating task:', error);
});
}
}Common Errors and Fixes
- Error: “refresh failed because configuration is not available” This error occurs if
refreshApexis called on an undefined or incorrect parameter. Always pass the exact result object returned by the wire service, as shown above. - Error: “Invalid Apex refresh call” Ensure you are not directly refreshing the wired method itself (e.g.,
refreshApex(getTodos)is incorrect). Instead, store the wire result in a variable and pass it torefreshApex.
Alternative Approach: Using then for Successful Server Calls
Another common solution involves chaining refreshApex inside a .then() block after the server-side operation completes successfully. Here’s an example:
callFromHtml() {
createTodo({ taskName: 'Another Task' })
.then((result) => {
if (result) {
console.log('Task created successfully');
}
// Refresh the wire result
return refreshApex(this.wiredTodos);
})
.catch((error) => {
console.error('Error:', error);
});
}Explanation of the Code: The createTodo method sends new task data to the server and returns a result upon success. Afterward, refreshApex is called with wiredTodos to ensure the component’s UI reflects the updated list of tasks. The .then() method ensures the data refresh happens only after the server-side operation completes successfully.
Common Errors and Fixes
- Error: “refresh failed because configuration is not available”
This error occurs ifrefreshApexis called on an undefined or incorrect parameter. Always pass the exact result object returned by the wire service, as shown above. - Error: “Invalid Apex refresh call”
Ensure you are not directly refreshing the wired method itself (e.g.,refreshApex(getTodos)is incorrect). Instead, store the wire result in a variable and pass it torefreshApex.
Key Takeaway
To refresh data in your LWC component using refreshApex, store the result of the @wire service in a variable. Use refreshApex with this stored result after a successful server operation. Following this pattern ensures your component updates dynamically without requiring a page refresh.
Summing Up
To sum up, when I want to refresh data dynamically in my LWC after CRUD operations, I make sure to store the result of my @wire call in a variable and use refreshApex with that stored result. This ensures that the UI updates seamlessly without needing a manual page refresh. By placing the refreshApex call inside the .then() block after a successful server operation, I avoid common errors and ensure that the data refresh happens only after the operation is completed. This approach keeps my component efficient and user-friendly.

