diff --git a/Examples/UIExplorer/TimerExample.js b/Examples/UIExplorer/TimerExample.js
new file mode 100644
index 000000000..6d48738d4
--- /dev/null
+++ b/Examples/UIExplorer/TimerExample.js
@@ -0,0 +1,193 @@
+/**
+ * Copyright 2004-present Facebook. All Rights Reserved.
+ */
+'use strict';
+
+var React = require('react-native');
+var {
+ AlertIOS,
+ StyleSheet,
+ Text,
+ TimerMixin,
+ TouchableHighlight,
+ View,
+} = React;
+
+var Button = React.createClass({
+ render: function() {
+ return (
+
+
+ {this.props.children}
+
+
+ );
+ },
+});
+
+var TimerTester = React.createClass({
+ mixins: [TimerMixin],
+
+ render: function() {
+ var args = 'fn' + (this.props.dt !== undefined ? ', ' + this.props.dt : '');
+ return (
+
+ );
+ },
+
+ _run: function() {
+ if (!this._start) {
+ var d = new Date();
+ this._start = d.getTime();
+ this._iters = 100;
+ this._ii = 0;
+ if (this.props.type === 'setTimeout') {
+ if (this.props.dt < 1) {
+ this._iters = 5000;
+ } else if (this.props.dt > 20) {
+ this._iters = 10;
+ }
+ this._timerFn = () => this.setTimeout(this._run, this.props.dt);
+ } else if (this.props.type === 'requestAnimationFrame') {
+ this._timerFn = () => this.requestAnimationFrame(this._run);
+ } else if (this.props.type === 'setImmediate') {
+ this._iters = 5000;
+ this._timerFn = () => this.setImmediate(this._run);
+ } else if (this.props.type === 'setInterval') {
+ this._iters = 30; // Only used for forceUpdate periodicidy
+ this._timerFn = null;
+ this._handle = this.setInterval(this._run, this.props.dt);
+ }
+ }
+ if (this._ii >= this._iters && !this._handle) {
+ var d = new Date();
+ var e = (d.getTime() - this._start);
+ var msg = 'Finished ' + this._ii + ' ' + this.props.type + ' calls.\n' +
+ 'Elapsed time: ' + e + ' ms\n' + (e / this._ii) + ' ms / iter';
+ console.log(msg);
+ AlertIOS.alert(msg);
+ this._start = null;
+ this.forceUpdate(() => { this._ii = 0; });
+ return;
+ }
+ this._ii++;
+ // Only re-render occasionally so we don't slow down timers.
+ if (this._ii % (this._iters / 5) === 0) {
+ this.forceUpdate();
+ }
+ this._timerFn && this._timerFn();
+ },
+
+ clear: function() {
+ this.clearInterval(this._handle); // invalid handles are ignored
+ if (this._handle) {
+ // Configure things so we can do a final run to update UI and reset state.
+ this._handle = null;
+ this._iters = this._ii;
+ this._run();
+ }
+ },
+});
+
+var styles = StyleSheet.create({
+ button: {
+ borderColor: 'gray',
+ borderRadius: 8,
+ borderWidth: 1,
+ padding: 10,
+ margin: 5,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+});
+
+exports.framework = 'React';
+exports.title = 'Timers, TimerMixin';
+exports.description = 'The TimerMixin provides timer functions for executing ' +
+ 'code in the future that are safely cleaned up when the component unmounts.';
+
+exports.examples = [
+ {
+ title: 'this.setTimeout(fn, t)',
+ description: 'Execute function fn t milliseconds in the future. If ' +
+ 't === 0, it will be enqueued immediately in the next event loop. ' +
+ 'Larger values will fire on the closest frame.',
+ render: function() {
+ return (
+
+
+
+
+
+ );
+ },
+ },
+ {
+ title: 'this.requestAnimationFrame(fn)',
+ description: 'Execute function fn on the next frame.',
+ render: function() {
+ return (
+
+
+
+ );
+ },
+ },
+ {
+ title: 'this.setImmediate(fn)',
+ description: 'Execute function fn at the end of the current JS event loop.',
+ render: function() {
+ return (
+
+
+
+ );
+ },
+ },
+ {
+ title: 'this.setInterval(fn, t)',
+ description: 'Execute function fn every t milliseconds until cancelled ' +
+ 'or component is unmounted.',
+ render: function() {
+ var IntervalExample = React.createClass({
+ getInitialState: function() {
+ return {
+ showTimer: true,
+ };
+ },
+
+ render: function() {
+ if (this.state.showTimer) {
+ var timer =
+ ;
+ var toggleText = 'Unmount timer';
+ } else {
+ var timer = null;
+ var toggleText = 'Mount new timer';
+ }
+ return (
+
+ {timer}
+
+
+
+ );
+ },
+
+ _toggleTimer: function() {
+ this.setState({showTimer: !this.state.showTimer});
+ },
+ });
+ return ;
+ },
+ },
+];
diff --git a/Examples/UIExplorer/UIExplorerList.js b/Examples/UIExplorer/UIExplorerList.js
index bc46292fd..39eaee5ca 100644
--- a/Examples/UIExplorer/UIExplorerList.js
+++ b/Examples/UIExplorer/UIExplorerList.js
@@ -20,6 +20,7 @@ var EXAMPLES = [
require('./ViewExample'),
require('./LayoutExample'),
require('./TextExample.ios'),
+ require('./TimerExample'),
require('./TextInputExample'),
require('./ExpandingTextExample'),
require('./ImageExample'),