MobX: Dynamically Adding Observables and Arrays
MobX is a popular library for managing state in React applications. One of its key features is the ability to make your data observable, allowing React components to re-render automatically when the data changes. However, dynamically adding properties to an observable object, especially arrays, can sometimes lead to unexpected behavior. This article delves into the nuances of working with observable objects and arrays in MobX, drawing insights from a question on Stack Overflow (https://stackoverflow.com/questions/48318449/mobx-add-new-array-property-to-observable-object).
Understanding the Problem
The user's code snippet demonstrates a common scenario: adding a new array property to an observable object upon fetching data from a network. However, the observable object's changes might not be detected by MobX. This is because, in MobX, the extendObservable
function only makes the existing object observable, not its future properties.
The Solution: Using set
The recommended approach for adding new properties to an observable object in MobX is using the set
function. Here's how the saveData
action can be rewritten:
@action
saveData(customerId, ordersForCustomer) {
set(this.data, { [customerId]: ordersForCustomer });
}
Explanation
set(object, properties)
: Theset
function takes two arguments: the target object and an object containing the properties to be set.set
Creates Observables: When usingset
, MobX automatically makes the new property (in this case, the arrayordersForCustomer
) observable. This ensures that changes within the array will trigger re-renders in your React components.
Example
import { observable, action, set } from "mobx";
class CustomerStore {
@observable data = {};
@action
saveData(customerId, ordersForCustomer) {
set(this.data, { [customerId]: ordersForCustomer });
}
}
const store = new CustomerStore();
store.saveData('123', [{ productId: 'abc', quantity: 2 }, { productId: 'def', quantity: 1 }]);
// Access the array
console.log(store.data['123']); // Outputs the orders array
// Modify the array (will trigger re-renders)
store.data['123'][0].quantity = 3;
Key Takeaway
Dynamically adding properties to an observable object requires using set
to ensure that MobX observes the new property and its internal changes. This helps maintain the reactivity and efficiency of your MobX-powered application.
Additional Considerations
- Array Modifications: While
set
handles the creation of new properties, you might need to use therunInAction
function for modifying the contents of an existing array, especially when handling asynchronous operations. - Immutability: When working with arrays, consider using techniques like
map
,filter
, andslice
to create new arrays instead of modifying the existing ones directly. This helps avoid performance issues and ensures your observable objects remain immutable.
By understanding these nuances and implementing the recommended practices, you can harness the power of MobX to build reactive and performant React applications.