Skip to content

Commit

Permalink
Implement event-specific pooling for SyntheticEvent (#10237)
Browse files Browse the repository at this point in the history
* Remove PooledClass from FallbackCompositionState

The only module that uses FallbackCompositonState is BeforeInputEventPlugin. The way its structured means there can only be a single instance of FallbackCompositionState at any given time (stored in a local variable at the top-level) so we don't really need pooling here at all. Instead, a single object is now stored in FallbackCompositionState, and access (initializing, reseting, getting data) is gaurded by the exported helper object.

* Use new FallbackCompositionState API in BeforeInputEventPlugin

* Implement event-specific pooling in SyntheticEvent

* Remove PooledClass from TopLevelCallbackBookKeeping

* Update results.json

* Add pooled event test fixtures (#1)

* Fix fixture lint
  • Loading branch information
aweary authored and gaearon committed Aug 4, 2017
1 parent efa7148 commit 755724a
Show file tree
Hide file tree
Showing 12 changed files with 368 additions and 159 deletions.
1 change: 1 addition & 0 deletions fixtures/dom/src/components/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class Header extends React.Component {
<option value="/buttons">Buttons</option>
<option value="/date-inputs">Date Inputs</option>
<option value="/error-handling">Error Handling</option>
<option value="/event-pooling">Event Pooling</option>
</select>
</label>
<label htmlFor="react_version">
Expand Down
38 changes: 38 additions & 0 deletions fixtures/dom/src/components/fixtures/event-pooling/hit-box.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const React = window.React;

class HitBox extends React.Component {
state = {
x: 0,
y: 0,
};

static defaultProps = {
onMouseMove: n => n,
};

onMove = event => {
this.setState({x: event.clientX, y: event.clientY});
this.props.onMouseMove(event);
};

render() {
const {x, y} = this.state;

const boxStyle = {
padding: '10px 20px',
border: '1px solid #d9d9d9',
margin: '10px 0 20px',
};

return (
<div onMouseMove={this.onMove} style={boxStyle}>
<p>Trace your mouse over this box.</p>
<p>
Last movement: {x},{y}
</p>
</div>
);
}
}

export default HitBox;
18 changes: 18 additions & 0 deletions fixtures/dom/src/components/fixtures/event-pooling/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import FixtureSet from '../../FixtureSet';
import MouseMove from './mouse-move';
import Persistence from './persistence';

const React = window.React;

class EventPooling extends React.Component {
render() {
return (
<FixtureSet title="Event Pooling" description="">
<MouseMove />
<Persistence />
</FixtureSet>
);
}
}

export default EventPooling;
51 changes: 51 additions & 0 deletions fixtures/dom/src/components/fixtures/event-pooling/mouse-move.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import TestCase from '../../TestCase';
import HitBox from './hit-box';

const React = window.React;

class MouseMove extends React.Component {
state = {
events: [],
};

checkEvent = event => {
let {events} = this.state;

if (event.type === 'mousemove' && events.indexOf(event) === -1) {
this.setState({events: events.concat(event)});
}
};

render() {
const {events} = this.state;

return (
<TestCase title="Mouse Move" description="">
<TestCase.Steps>
<li>Mouse over the box below</li>
</TestCase.Steps>

<TestCase.ExpectedResult>
Mousemove should share the same instance of the event between
dispatches.
</TestCase.ExpectedResult>

<HitBox onMouseMove={this.checkEvent} />

<p>
Was the event pooled?{' '}
<b>
{events.length ? events.length <= 1 ? 'Yes' : 'No' : 'Unsure'}
{' '}
(
{events.length}
{' '}
events)
</b>
</p>
</TestCase>
);
}
}

export default MouseMove;
65 changes: 65 additions & 0 deletions fixtures/dom/src/components/fixtures/event-pooling/persistence.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import TestCase from '../../TestCase';
import HitBox from './hit-box';

const React = window.React;

class Persistence extends React.Component {
state = {
persisted: 0,
pooled: [],
};

addPersisted = event => {
let {persisted, pooled} = this.state;

event.persist();

if (event.type === 'mousemove') {
this.setState({
persisted: persisted + 1,
pooled: pooled.filter(e => e !== event),
});
}
};

addPooled = event => {
let {pooled} = this.state;

if (event.type === 'mousemove' && pooled.indexOf(event) === -1) {
this.setState({pooled: pooled.concat(event)});
}
};

render() {
const {pooled, persisted} = this.state;

return (
<TestCase title="Persistence" description="">
<TestCase.Steps>
<li>Mouse over the pooled event box</li>
<li>Mouse over the persisted event box</li>
</TestCase.Steps>

<TestCase.ExpectedResult>
The pool size should not increase above 1, but reduce to 0 when hovering over the persisted region.
</TestCase.ExpectedResult>

<h2>Add Pooled Event:</h2>
<HitBox onMouseMove={this.addPooled} />

<h2>Add Persisted Event:</h2>
<HitBox onMouseMove={this.addPersisted} />

<p>
Pool size: {pooled.length}
</p>

<p>
Persisted size: {persisted}
</p>
</TestCase>
);
}
}

export default Persistence;
3 changes: 3 additions & 0 deletions fixtures/dom/src/components/fixtures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import PasswordInputFixtures from './password-inputs';
import ButtonFixtures from './buttons';
import DateInputFixtures from './date-inputs';
import ErrorHandling from './error-handling';
import EventPooling from './event-pooling';

const React = window.React;

Expand Down Expand Up @@ -37,6 +38,8 @@ function FixturesPage() {
return <DateInputFixtures />;
case '/error-handling':
return <ErrorHandling />;
case '/event-pooling':
return <EventPooling />;
default:
return <p>Please select a test fixture.</p>;
}
Expand Down
Loading

0 comments on commit 755724a

Please sign in to comment.