Batch Update
Generally, when updating multiple states, multiple set
events will be triggered. In React
scenarios, for rendering optimization, we might want to update multiple states at once, triggering only one render.
AutoStore
has a built-in batch update mechanism
. Below we'll introduce its working mechanism and how to use it.
Working Mechanism
const sore = new AutoStore({
name:"Fisher"
age:18
})
- First, when executing
store.state.name='Wang'
andstore.state.age=20
, twoset
events will be triggered.
{
"type":"set",
"path":["name"],
"value":"Wang"
}
{
"type":"set",
"path":["age"],
"value":20
}
- Normally,
set
events will triggerReact
component re-rendering, but if we want to update multiple states at once and trigger only one render, we can use thebatchUpdate
method.
store.batchUpdate(state=>{
store.state.name='Wang'
store.state.age=20
})
The
batchUpdate
method setsstore._batching
totrue
, then executesstore.state.name='Wang'
andstore.state.age=20
, which triggers twoset
events.However, since
store._batching=true
, these twoset
events will be intercepted and collected instore._batchOperates
.After executing the state updates,
store.batching
is set back tofalse
.Here comes the key part: two operations are performed:
- All
set
events instore._batchOperates
are marked withreply=true
, indicating these are replay events after a batch update operation. This ensures normal subscribers receiveset
events, while during batch update optimization, these events can be ignored by checkingreply=true
.
ts{ "type":"set", "path":["name"], "value":"Wang", "reply":true } { "type":"set", "path":["age"], "value":20, "reply":true }
- Then all
set
events instore._batchOperates
are merged into onebatch
type event, as follows:
ts{ "type":"batch", "path":["__batch_update__"], "value":[ { "type":"set", "path":["name"], "value":"Wang", "reply":true }, { "type":"set", "path":["age"], "value":20, "reply":true } ] }
- All
- Following the above principle, when executing a batch update operation:
store.batchUpdate(state=>{
store.state.name='Wang'
store.state.age=20
})
Three events will be triggered, as follows:
// Replay event
{
"type":"set",
"path":["name"],
"value":"Wang",
"reply":true
}
// Replay event
{
"type":"set",
"path":["age"],
"value":20,
"reply":true
}
// Merged batch event
{
"type":"batch",
"path":["__batch_update__"],
"value":[
{
"type":"set",
"path":["name"],
"value":"Wang",
"reply":true
},
{
"type":"set",
"path":["age"],
"value":20,
"reply":true
}
]
}
For rendering optimization, you just need to: ignore replay events after batch update
and respond to the merged batch event after batch update
, as follows:
store.watch((operate)=>{
if(operate.reply) return // This is a replay event after batch update, ignore it
if(operate.type==='batch'){
// Trigger one render here
}
})