mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
batchedUpdates tests
Covers some bugs I encountered while working on this feature. Introduces a syncUpdates API to ReactNoop. Is this something we'd want to expose to the reconciler?
This commit is contained in:
@@ -257,6 +257,10 @@ var ReactNoop = {
|
||||
NoopRenderer.performWithPriority(AnimationPriority, fn);
|
||||
},
|
||||
|
||||
batchedUpdates: NoopRenderer.batchedUpdates,
|
||||
|
||||
syncUpdates: NoopRenderer.syncUpdates,
|
||||
|
||||
// Logs the current state of the tree.
|
||||
dumpTree(rootID : string = DEFAULT_ROOT_ID) {
|
||||
const root = roots.get(rootID);
|
||||
|
||||
@@ -71,6 +71,7 @@ export type Reconciler<C, I, TI> = {
|
||||
/* eslint-disable no-undef */
|
||||
// FIXME: ESLint complains about type parameter
|
||||
batchedUpdates<A>(fn : () => A) : A,
|
||||
syncUpdates<A>(fn : () => A) : A,
|
||||
/* eslint-enable no-undef */
|
||||
|
||||
// Used to extract the return value from the initial render. Legacy API.
|
||||
@@ -86,6 +87,7 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) :
|
||||
scheduleWork,
|
||||
performWithPriority,
|
||||
batchedUpdates,
|
||||
syncUpdates,
|
||||
} = ReactFiberScheduler(config);
|
||||
|
||||
return {
|
||||
@@ -152,6 +154,8 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) :
|
||||
|
||||
batchedUpdates,
|
||||
|
||||
syncUpdates,
|
||||
|
||||
getPublicRootInstance(container : OpaqueNode) : (ReactComponent<any, any, any> | I | TI | null) {
|
||||
const root : FiberRoot = (container.stateNode : any);
|
||||
const containerFiber = root.current;
|
||||
|
||||
@@ -712,10 +712,21 @@ module.exports = function<T, P, I, TI, C>(config : HostConfig<T, P, I, TI, C>) {
|
||||
}
|
||||
}
|
||||
|
||||
function syncUpdates<A>(fn : () => A) : A {
|
||||
const previousPriorityContext = priorityContext;
|
||||
priorityContext = SynchronousPriority;
|
||||
try {
|
||||
return fn();
|
||||
} finally {
|
||||
priorityContext = previousPriorityContext;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
scheduleWork: scheduleWork,
|
||||
scheduleDeferredWork: scheduleDeferredWork,
|
||||
performWithPriority: performWithPriority,
|
||||
batchedUpdates: batchedUpdates,
|
||||
syncUpdates: syncUpdates,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1386,4 +1386,83 @@ describe('ReactIncremental', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('performs batched updates at the end of the batch', () => {
|
||||
var ops = [];
|
||||
var instance;
|
||||
|
||||
class Foo extends React.Component {
|
||||
state = { n: 0 };
|
||||
render() {
|
||||
instance = this;
|
||||
return <div />;
|
||||
}
|
||||
}
|
||||
|
||||
ReactNoop.render(<Foo />);
|
||||
ReactNoop.flush();
|
||||
ops = [];
|
||||
|
||||
ReactNoop.syncUpdates(() => {
|
||||
ReactNoop.batchedUpdates(() => {
|
||||
instance.setState({ n: 1 }, () => ops.push('setState 1'));
|
||||
instance.setState({ n: 2 }, () => ops.push('setState 2'));
|
||||
ops.push('end batchedUpdates');
|
||||
});
|
||||
ops.push('end syncUpdates');
|
||||
});
|
||||
|
||||
// ReactNoop.flush() not needed because updates are synchronous
|
||||
|
||||
expect(ops).toEqual([
|
||||
'end batchedUpdates',
|
||||
'setState 1',
|
||||
'setState 2',
|
||||
'end syncUpdates',
|
||||
]);
|
||||
expect(instance.state.n).toEqual(2);
|
||||
});
|
||||
|
||||
it('can nest batchedUpdates', () => {
|
||||
var ops = [];
|
||||
var instance;
|
||||
|
||||
class Foo extends React.Component {
|
||||
state = { n: 0 };
|
||||
render() {
|
||||
instance = this;
|
||||
return <div />;
|
||||
}
|
||||
}
|
||||
|
||||
ReactNoop.render(<Foo />);
|
||||
ReactNoop.flush();
|
||||
ops = [];
|
||||
|
||||
ReactNoop.syncUpdates(() => {
|
||||
ReactNoop.batchedUpdates(() => {
|
||||
instance.setState({ n: 1 }, () => ops.push('setState 1'));
|
||||
instance.setState({ n: 2 }, () => ops.push('setState 2'));
|
||||
ReactNoop.batchedUpdates(() => {
|
||||
instance.setState({ n: 3 }, () => ops.push('setState 3'));
|
||||
instance.setState({ n: 4 }, () => ops.push('setState 4'));
|
||||
ops.push('end inner batchedUpdates');
|
||||
});
|
||||
ops.push('end outer batchedUpdates');
|
||||
});
|
||||
ops.push('end syncUpdates');
|
||||
});
|
||||
|
||||
// ReactNoop.flush() not needed because updates are synchronous
|
||||
|
||||
expect(ops).toEqual([
|
||||
'end inner batchedUpdates',
|
||||
'end outer batchedUpdates',
|
||||
'setState 1',
|
||||
'setState 2',
|
||||
'setState 3',
|
||||
'setState 4',
|
||||
'end syncUpdates',
|
||||
]);
|
||||
expect(instance.state.n).toEqual(4);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user