I'm using Facebook ComponentsKit to generate my views.
I now am migrating to a "flux" architecture for changing app state and triggering view updates.
The main problem I have is that not all state changes should trigger a UI update. I don't understand the "generic" mechanism to avoid that.
Basically the app state is a "big" "JSON" representing a "view model" (Parsed to native typed objects). The JSON contains all of the view declarations and their initial values. (The JSON is quite complex)
For example a simplified JSON representing a view hierarchy containing a "pager" component and a navigation "next" button :
{
... views ...
{
"pager" : {
"id" : "pager-id-xxx",
"currentPage" : 0,
"pages" : [
....pages....
{},
{},
....pages....
]
},
...
"navigation-next-button" : {
"id" : "navigation-next-button-id-xxxx",
"target" : "pager-id-xxx"
}
},
... views ...
}
My "Flux" abstraction looks like:
// "Action" portion
@interface ChangePageAction
@property id destinationId; // very simplified action. wraps the destination "id"
@end
@implementation ChangePageReducer
-(JSON)reduce:(JSON)initialJSON action:(ChangePageAction *)changePageAction {
// the "reduce" portion finds the node of the pager (in the JSON) and changes the value by +1
// something like:
// find the node in the JSON with the changePageAction.destinationID
Node *nodeCopy = getNodeCopy(initialJSON,changePageAction.destinationId);
replaceValue(nodeCopy,nodeCopy.currentPage + 1);
// according to FLUX doctrine we are supposed to return a new object
return jsonCopyByReplacingNode(nodeCopy); // a new JSON with the updated values
}
// the navigation button triggers the new state
@implementation NavigationNextButton {
id _destination; // the target of this action
FluxStore _store; // the application flux store
}
-(void)buttonPressed {
ChangePageAction *changePage = ...
[_store dispatch:changePage];
}
@end
In my "view controller" I now get a "update state" callback
@implementation ViewController
-(void)newState:(JSON)newJSON {
// here all of the view is re-rendered
[self render:JSON];
//The issue is that I don't need or want to re-render for every action that is performed on the state.
// many states don't evaluate to a UI update
// how should I manage that?
}
@end
Unfortunately, there's no easy way to do this in ComponentKit. React has shouldComponentUpdate
, but ComponentKit does not have an equivalent.
The good news is that ComponentKit should be smart enough to rebuild all the components, then realize that nothing has actually changed, and end up making no UIKit changes.
The bad news is that it'll spend a fair amount of CPU doing that.