diff --git a/src/react-components/name-entry-panel.js b/src/react-components/name-entry-panel.js
new file mode 100644
index 0000000000000000000000000000000000000000..fb0022efc02e8694d11beafdef83198399db94bf
--- /dev/null
+++ b/src/react-components/name-entry-panel.js
@@ -0,0 +1,48 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { SCHEMA } from "../storage/store";
+
+export default class NameEntryPanel extends Component {
+  static propTypes = {
+    store: PropTypes.object
+  }
+
+  constructor(props) {
+    super(props);
+    window.store = this.props.store;
+    this.state = {name: this.props.store.state.profile.display_name};
+    this.props.store.subscribe(() => {
+      this.setState({name: this.props.store.state.profile.display_name});
+    });
+  }
+
+  saveName = (e) => {
+    e.preventDefault();
+    this.props.store.update({ profile: { display_name: this.nameInput.value } });
+  }
+
+  componentDidMount() {
+    // stop propagation so that avatar doesn't move when wasd'ing during text input.
+    this.nameInput.addEventListener('keydown', e => e.stopPropagation());
+    this.nameInput.addEventListener('keypress', e => e.stopPropagation());
+    this.nameInput.addEventListener('keyup', e => e.stopPropagation());
+  }
+
+  render () {
+    return (
+      <div>
+        Name Entry
+        <form onSubmit={this.saveName}>
+          <label>Name:
+            <input
+              value={this.state.name} onChange={(e) => this.setState({name: e.target.value})}
+              required pattern={SCHEMA.definitions.profile.properties.display_name.pattern}
+              title="Alphanumerics and hyphens. At least 3 characters, no more than 32"
+              ref={inp => this.nameInput = inp}/>
+          </label>
+          <input type="submit" value="Save" />
+        </form>
+      </div>
+    );
+  }
+}
diff --git a/src/react-components/ui-root.js b/src/react-components/ui-root.js
index 1d95826d766237291daeb68ee697fc5adca700d1..0fdeb428826e1616884a8d3f62db8353a41e4e9a 100644
--- a/src/react-components/ui-root.js
+++ b/src/react-components/ui-root.js
@@ -1,6 +1,7 @@
 import React, { Component } from 'react';
 import PropTypes from 'prop-types';
-import { VR_DEVICE_AVAILABILITY } from "../utils/vr-caps-detect.js";
+import NameEntryPanel from './name-entry-panel';
+import { VR_DEVICE_AVAILABILITY } from "../utils/vr-caps-detect";
 import queryString from "query-string";
 import { SCHEMA } from "../storage/store";
 const { detect } = require("detect-browser");
@@ -346,11 +347,6 @@ class UIRoot extends Component {
     this.setState({ entryStep: ENTRY_STEPS.finished });
   }
 
-  saveName = (e) => {
-    e.preventDefault();
-    this.props.store.update({ profile: { display_name: this.nameInput.value } });
-  }
-
   render() {
     if (!this.state.sceneLoaded) {
       return (
@@ -398,22 +394,6 @@ class UIRoot extends Component {
         </div>
       ) : null;
 
-    const nameEntryPanel = (
-      <div>
-        Name Entry
-        <form onSubmit={this.saveName}>
-          <label>Name:
-            <input
-              defaultValue={this.props.store.state.profile.display_name}
-              required pattern={SCHEMA.definitions.profile.properties.display_name.pattern}
-              title="Alphanumerics and hyphens. At least 3 characters, no more than 32"
-              ref={inp => this.nameInput = inp}/>
-          </label>
-          <input type="submit" value="Save" />
-        </form>
-      </div>
-    );
-
     const overlay = this.isWaitingForAutoExit() ?
       (<AutoExitWarning secondsRemaining={this.state.secondsRemainingBeforeAutoExit} onCancel={this.endAutoExitTimer} />) :
       (
@@ -422,7 +402,7 @@ class UIRoot extends Component {
           {micPanel}
           {audioSetupPanel}
 
-          {nameEntryPanel}
+          <NameEntryPanel store={this.props.store}></NameEntryPanel>
         </div>
       );