diff --git a/src/Modal.js b/src/Modal.js
index 68d75d1ff1..c9f08772e7 100644
--- a/src/Modal.js
+++ b/src/Modal.js
@@ -19,6 +19,7 @@ limitations under the License.
 
 const React = require('react');
 const ReactDOM = require('react-dom');
+import PropTypes from 'prop-types';
 import Analytics from './Analytics';
 import sdk from './index';
 
@@ -33,7 +34,7 @@ const AsyncWrapper = React.createClass({
         /** A function which takes a 'callback' argument which it will call
          * with the real component once it loads.
          */
-        loader: React.PropTypes.func.isRequired,
+        loader: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/Velociraptor.js b/src/Velociraptor.js
index 9a674d4f09..af4e6dcb60 100644
--- a/src/Velociraptor.js
+++ b/src/Velociraptor.js
@@ -1,5 +1,6 @@
 const React = require('react');
 const ReactDom = require('react-dom');
+import PropTypes from 'prop-types';
 const Velocity = require('velocity-vector');
 
 /**
@@ -14,16 +15,16 @@ module.exports = React.createClass({
 
     propTypes: {
         // either a list of child nodes, or a single child.
-        children: React.PropTypes.any,
+        children: PropTypes.any,
 
         // optional transition information for changing existing children
-        transition: React.PropTypes.object,
+        transition: PropTypes.object,
 
         // a list of state objects to apply to each child node in turn
-        startStyles: React.PropTypes.array,
+        startStyles: PropTypes.array,
 
         // a list of transition options from the corresponding startStyle
-        enterTransitionOpts: React.PropTypes.array,
+        enterTransitionOpts: PropTypes.array,
     },
 
     getDefaultProps: function() {
diff --git a/src/async-components/views/dialogs/EncryptedEventDialog.js b/src/async-components/views/dialogs/EncryptedEventDialog.js
index a8f588d39a..5db8b2365f 100644
--- a/src/async-components/views/dialogs/EncryptedEventDialog.js
+++ b/src/async-components/views/dialogs/EncryptedEventDialog.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 const React = require("react");
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 const sdk = require('../../../index');
 const MatrixClientPeg = require("../../../MatrixClientPeg");
@@ -23,8 +24,8 @@ module.exports = React.createClass({
     displayName: 'EncryptedEventDialog',
 
     propTypes: {
-        event: React.PropTypes.object.isRequired,
-        onFinished: React.PropTypes.func.isRequired,
+        event: PropTypes.object.isRequired,
+        onFinished: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/async-components/views/dialogs/ExportE2eKeysDialog.js b/src/async-components/views/dialogs/ExportE2eKeysDialog.js
index 04274442c2..06fb0668d5 100644
--- a/src/async-components/views/dialogs/ExportE2eKeysDialog.js
+++ b/src/async-components/views/dialogs/ExportE2eKeysDialog.js
@@ -16,6 +16,7 @@ limitations under the License.
 
 import FileSaver from 'file-saver';
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
 import * as Matrix from 'matrix-js-sdk';
@@ -29,8 +30,8 @@ export default React.createClass({
     displayName: 'ExportE2eKeysDialog',
 
     propTypes: {
-        matrixClient: React.PropTypes.instanceOf(Matrix.MatrixClient).isRequired,
-        onFinished: React.PropTypes.func.isRequired,
+        matrixClient: PropTypes.instanceOf(Matrix.MatrixClient).isRequired,
+        onFinished: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/async-components/views/dialogs/ImportE2eKeysDialog.js b/src/async-components/views/dialogs/ImportE2eKeysDialog.js
index a01b6580f1..10744a8911 100644
--- a/src/async-components/views/dialogs/ImportE2eKeysDialog.js
+++ b/src/async-components/views/dialogs/ImportE2eKeysDialog.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import * as Matrix from 'matrix-js-sdk';
 import * as MegolmExportEncryption from '../../../utils/MegolmExportEncryption';
@@ -40,8 +41,8 @@ export default React.createClass({
     displayName: 'ImportE2eKeysDialog',
 
     propTypes: {
-        matrixClient: React.PropTypes.instanceOf(Matrix.MatrixClient).isRequired,
-        onFinished: React.PropTypes.func.isRequired,
+        matrixClient: PropTypes.instanceOf(Matrix.MatrixClient).isRequired,
+        onFinished: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/autocomplete/Components.js b/src/autocomplete/Components.js
index a27533f7c2..b09f4e963e 100644
--- a/src/autocomplete/Components.js
+++ b/src/autocomplete/Components.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import classNames from 'classnames';
 
 /* These were earlier stateless functional components but had to be converted
@@ -42,10 +43,10 @@ export class TextualCompletion extends React.Component {
     }
 }
 TextualCompletion.propTypes = {
-    title: React.PropTypes.string,
-    subtitle: React.PropTypes.string,
-    description: React.PropTypes.string,
-    className: React.PropTypes.string,
+    title: PropTypes.string,
+    subtitle: PropTypes.string,
+    description: PropTypes.string,
+    className: PropTypes.string,
 };
 
 export class PillCompletion extends React.Component {
@@ -69,9 +70,9 @@ export class PillCompletion extends React.Component {
     }
 }
 PillCompletion.propTypes = {
-    title: React.PropTypes.string,
-    subtitle: React.PropTypes.string,
-    description: React.PropTypes.string,
-    initialComponent: React.PropTypes.element,
-    className: React.PropTypes.string,
+    title: PropTypes.string,
+    subtitle: PropTypes.string,
+    description: PropTypes.string,
+    initialComponent: PropTypes.element,
+    className: PropTypes.string,
 };
diff --git a/src/components/structures/ContextualMenu.js b/src/components/structures/ContextualMenu.js
index 3c2308e6a7..94f5713a79 100644
--- a/src/components/structures/ContextualMenu.js
+++ b/src/components/structures/ContextualMenu.js
@@ -20,6 +20,7 @@ limitations under the License.
 const classNames = require('classnames');
 const React = require('react');
 const ReactDOM = require('react-dom');
+import PropTypes from 'prop-types';
 
 // Shamelessly ripped off Modal.js.  There's probably a better way
 // of doing reusable widgets like dialog boxes & menus where we go and
@@ -29,11 +30,11 @@ module.exports = {
     ContextualMenuContainerId: "mx_ContextualMenu_Container",
 
     propTypes: {
-        menuWidth: React.PropTypes.number,
-        menuHeight: React.PropTypes.number,
-        chevronOffset: React.PropTypes.number,
-        menuColour: React.PropTypes.string,
-        chevronFace: React.PropTypes.string, // top, bottom, left, right
+        menuWidth: PropTypes.number,
+        menuHeight: PropTypes.number,
+        chevronOffset: PropTypes.number,
+        menuColour: PropTypes.string,
+        chevronFace: PropTypes.string, // top, bottom, left, right
     },
 
     getOrCreateContainer: function() {
diff --git a/src/components/structures/CreateRoom.js b/src/components/structures/CreateRoom.js
index 26454c5ea6..2bb9adb544 100644
--- a/src/components/structures/CreateRoom.js
+++ b/src/components/structures/CreateRoom.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t } from '../../languageHandler';
 import sdk from '../../index';
 import MatrixClientPeg from '../../MatrixClientPeg';
@@ -30,8 +31,8 @@ module.exports = React.createClass({
     displayName: 'CreateRoom',
 
     propTypes: {
-        onRoomCreated: React.PropTypes.func,
-        collapsedRhs: React.PropTypes.bool,
+        onRoomCreated: PropTypes.func,
+        collapsedRhs: PropTypes.bool,
     },
 
     phases: {
diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js
index ffa5e45249..e86b76333d 100644
--- a/src/components/structures/FilePanel.js
+++ b/src/components/structures/FilePanel.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import Matrix from 'matrix-js-sdk';
 import sdk from '../../index';
@@ -28,7 +29,7 @@ const FilePanel = React.createClass({
     displayName: 'FilePanel',
 
     propTypes: {
-        roomId: React.PropTypes.string.isRequired,
+        roomId: PropTypes.string.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js
index 5ffb97c6ed..8bb6ba49b0 100644
--- a/src/components/structures/GroupView.js
+++ b/src/components/structures/GroupView.js
@@ -390,7 +390,7 @@ const FeaturedUser = React.createClass({
 });
 
 const GroupContext = {
-    groupStore: React.PropTypes.instanceOf(GroupStore).isRequired,
+    groupStore: PropTypes.instanceOf(GroupStore).isRequired,
 };
 
 CategoryRoomList.contextTypes = GroupContext;
@@ -408,7 +408,7 @@ export default React.createClass({
     },
 
     childContextTypes: {
-        groupStore: React.PropTypes.instanceOf(GroupStore),
+        groupStore: PropTypes.instanceOf(GroupStore),
     },
 
     getChildContext: function() {
diff --git a/src/components/structures/InteractiveAuth.js b/src/components/structures/InteractiveAuth.js
index 8a2c1b8c79..8428e3c714 100644
--- a/src/components/structures/InteractiveAuth.js
+++ b/src/components/structures/InteractiveAuth.js
@@ -18,6 +18,7 @@ import Matrix from 'matrix-js-sdk';
 const InteractiveAuth = Matrix.InteractiveAuth;
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import {getEntryComponentForLoginType} from '../views/login/InteractiveAuthEntryComponents';
 
@@ -26,18 +27,18 @@ export default React.createClass({
 
     propTypes: {
         // matrix client to use for UI auth requests
-        matrixClient: React.PropTypes.object.isRequired,
+        matrixClient: PropTypes.object.isRequired,
 
         // response from initial request. If not supplied, will do a request on
         // mount.
-        authData: React.PropTypes.shape({
-            flows: React.PropTypes.array,
-            params: React.PropTypes.object,
-            session: React.PropTypes.string,
+        authData: PropTypes.shape({
+            flows: PropTypes.array,
+            params: PropTypes.object,
+            session: PropTypes.string,
         }),
 
         // callback
-        makeRequest: React.PropTypes.func.isRequired,
+        makeRequest: PropTypes.func.isRequired,
 
         // callback called when the auth process has finished,
         // successfully or unsuccessfully.
@@ -51,22 +52,22 @@ export default React.createClass({
         //            the auth session.
         //      * clientSecret {string} The client secret used in auth
         //            sessions with the ID server.
-        onAuthFinished: React.PropTypes.func.isRequired,
+        onAuthFinished: PropTypes.func.isRequired,
 
         // Inputs provided by the user to the auth process
         // and used by various stages. As passed to js-sdk
         // interactive-auth
-        inputs: React.PropTypes.object,
+        inputs: PropTypes.object,
 
         // As js-sdk interactive-auth
-        makeRegistrationUrl: React.PropTypes.func,
-        sessionId: React.PropTypes.string,
-        clientSecret: React.PropTypes.string,
-        emailSid: React.PropTypes.string,
+        makeRegistrationUrl: PropTypes.func,
+        sessionId: PropTypes.string,
+        clientSecret: PropTypes.string,
+        emailSid: PropTypes.string,
 
         // If true, poll to see if the auth flow has been completed
         // out-of-band
-        poll: React.PropTypes.bool,
+        poll: PropTypes.bool,
     },
 
     getInitialState: function() {
diff --git a/src/components/structures/LoggedInView.js b/src/components/structures/LoggedInView.js
index 6f40aa559a..bebc109806 100644
--- a/src/components/structures/LoggedInView.js
+++ b/src/components/structures/LoggedInView.js
@@ -18,6 +18,7 @@ limitations under the License.
 
 import * as Matrix from 'matrix-js-sdk';
 import React from 'react';
+import PropTypes from 'prop-types';
 import { DragDropContext } from 'react-dnd';
 import HTML5Backend from 'react-dnd-html5-backend';
 
@@ -44,23 +45,23 @@ const LoggedInView = React.createClass({
     displayName: 'LoggedInView',
 
     propTypes: {
-        matrixClient: React.PropTypes.instanceOf(Matrix.MatrixClient).isRequired,
-        page_type: React.PropTypes.string.isRequired,
-        onRoomCreated: React.PropTypes.func,
-        onUserSettingsClose: React.PropTypes.func,
+        matrixClient: PropTypes.instanceOf(Matrix.MatrixClient).isRequired,
+        page_type: PropTypes.string.isRequired,
+        onRoomCreated: PropTypes.func,
+        onUserSettingsClose: PropTypes.func,
 
         // Called with the credentials of a registered user (if they were a ROU that
         // transitioned to PWLU)
-        onRegistered: React.PropTypes.func,
+        onRegistered: PropTypes.func,
 
-        teamToken: React.PropTypes.string,
+        teamToken: PropTypes.string,
 
         // and lots and lots of other stuff.
     },
 
     childContextTypes: {
-        matrixClient: React.PropTypes.instanceOf(Matrix.MatrixClient),
-        authCache: React.PropTypes.object,
+        matrixClient: PropTypes.instanceOf(Matrix.MatrixClient),
+        authCache: PropTypes.object,
     },
 
     getChildContext: function() {
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index 3452d13841..733007677b 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -19,6 +19,7 @@ limitations under the License.
 import Promise from 'bluebird';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import Matrix from "matrix-js-sdk";
 
 import Analytics from "../../Analytics";
@@ -92,38 +93,38 @@ export default React.createClass({
     displayName: 'MatrixChat',
 
     propTypes: {
-        config: React.PropTypes.object,
-        ConferenceHandler: React.PropTypes.any,
-        onNewScreen: React.PropTypes.func,
-        registrationUrl: React.PropTypes.string,
-        enableGuest: React.PropTypes.bool,
+        config: PropTypes.object,
+        ConferenceHandler: PropTypes.any,
+        onNewScreen: PropTypes.func,
+        registrationUrl: PropTypes.string,
+        enableGuest: PropTypes.bool,
 
         // the queryParams extracted from the [real] query-string of the URI
-        realQueryParams: React.PropTypes.object,
+        realQueryParams: PropTypes.object,
 
         // the initial queryParams extracted from the hash-fragment of the URI
-        startingFragmentQueryParams: React.PropTypes.object,
+        startingFragmentQueryParams: PropTypes.object,
 
         // called when we have completed a token login
-        onTokenLoginCompleted: React.PropTypes.func,
+        onTokenLoginCompleted: PropTypes.func,
 
         // Represents the screen to display as a result of parsing the initial
         // window.location
-        initialScreenAfterLogin: React.PropTypes.shape({
-            screen: React.PropTypes.string.isRequired,
-            params: React.PropTypes.object,
+        initialScreenAfterLogin: PropTypes.shape({
+            screen: PropTypes.string.isRequired,
+            params: PropTypes.object,
         }),
 
         // displayname, if any, to set on the device when logging
         // in/registering.
-        defaultDeviceDisplayName: React.PropTypes.string,
+        defaultDeviceDisplayName: PropTypes.string,
 
         // A function that makes a registration URL
-        makeRegistrationUrl: React.PropTypes.func.isRequired,
+        makeRegistrationUrl: PropTypes.func.isRequired,
     },
 
     childContextTypes: {
-        appConfig: React.PropTypes.object,
+        appConfig: PropTypes.object,
     },
 
     AuxPanel: {
diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js
index 53cc660a9b..84441e1317 100644
--- a/src/components/structures/MessagePanel.js
+++ b/src/components/structures/MessagePanel.js
@@ -16,6 +16,7 @@ limitations under the License.
 
 import React from 'react';
 import ReactDOM from 'react-dom';
+import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import shouldHideEvent from '../../shouldHideEvent';
 import dis from "../../dispatcher";
@@ -32,63 +33,63 @@ module.exports = React.createClass({
 
     propTypes: {
         // true to give the component a 'display: none' style.
-        hidden: React.PropTypes.bool,
+        hidden: PropTypes.bool,
 
         // true to show a spinner at the top of the timeline to indicate
         // back-pagination in progress
-        backPaginating: React.PropTypes.bool,
+        backPaginating: PropTypes.bool,
 
         // true to show a spinner at the end of the timeline to indicate
         // forward-pagination in progress
-        forwardPaginating: React.PropTypes.bool,
+        forwardPaginating: PropTypes.bool,
 
         // the list of MatrixEvents to display
-        events: React.PropTypes.array.isRequired,
+        events: PropTypes.array.isRequired,
 
         // ID of an event to highlight. If undefined, no event will be highlighted.
-        highlightedEventId: React.PropTypes.string,
+        highlightedEventId: PropTypes.string,
 
         // Should we show URL Previews
-        showUrlPreview: React.PropTypes.bool,
+        showUrlPreview: PropTypes.bool,
 
         // event after which we should show a read marker
-        readMarkerEventId: React.PropTypes.string,
+        readMarkerEventId: PropTypes.string,
 
         // whether the read marker should be visible
-        readMarkerVisible: React.PropTypes.bool,
+        readMarkerVisible: PropTypes.bool,
 
         // the userid of our user. This is used to suppress the read marker
         // for pending messages.
-        ourUserId: React.PropTypes.string,
+        ourUserId: PropTypes.string,
 
         // true to suppress the date at the start of the timeline
-        suppressFirstDateSeparator: React.PropTypes.bool,
+        suppressFirstDateSeparator: PropTypes.bool,
 
         // whether to show read receipts
-        showReadReceipts: React.PropTypes.bool,
+        showReadReceipts: PropTypes.bool,
 
         // true if updates to the event list should cause the scroll panel to
         // scroll down when we are at the bottom of the window. See ScrollPanel
         // for more details.
-        stickyBottom: React.PropTypes.bool,
+        stickyBottom: PropTypes.bool,
 
         // callback which is called when the panel is scrolled.
-        onScroll: React.PropTypes.func,
+        onScroll: PropTypes.func,
 
         // callback which is called when more content is needed.
-        onFillRequest: React.PropTypes.func,
+        onFillRequest: PropTypes.func,
 
         // className for the panel
-        className: React.PropTypes.string.isRequired,
+        className: PropTypes.string.isRequired,
 
         // shape parameter to be passed to EventTiles
-        tileShape: React.PropTypes.string,
+        tileShape: PropTypes.string,
 
         // show twelve hour timestamps
-        isTwelveHour: React.PropTypes.bool,
+        isTwelveHour: PropTypes.bool,
 
         // show timestamps always
-        alwaysShowTimestamps: React.PropTypes.bool,
+        alwaysShowTimestamps: PropTypes.bool,
     },
 
     componentWillMount: function() {
diff --git a/src/components/structures/MyGroups.js b/src/components/structures/MyGroups.js
index 9281fb199e..22157beaca 100644
--- a/src/components/structures/MyGroups.js
+++ b/src/components/structures/MyGroups.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import GeminiScrollbar from 'react-gemini-scrollbar';
 import sdk from '../../index';
 import { _t } from '../../languageHandler';
@@ -26,7 +27,7 @@ export default withMatrixClient(React.createClass({
     displayName: 'MyGroups',
 
     propTypes: {
-        matrixClient: React.PropTypes.object.isRequired,
+        matrixClient: PropTypes.object.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js
index 77d506d9af..4f9de7eac9 100644
--- a/src/components/structures/RoomStatusBar.js
+++ b/src/components/structures/RoomStatusBar.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import Matrix from 'matrix-js-sdk';
 import { _t } from '../../languageHandler';
 import sdk from '../../index';
@@ -41,59 +42,59 @@ module.exports = React.createClass({
 
     propTypes: {
         // the room this statusbar is representing.
-        room: React.PropTypes.object.isRequired,
+        room: PropTypes.object.isRequired,
 
         // the number of messages which have arrived since we've been scrolled up
-        numUnreadMessages: React.PropTypes.number,
+        numUnreadMessages: PropTypes.number,
 
         // this is true if we are fully scrolled-down, and are looking at
         // the end of the live timeline.
-        atEndOfLiveTimeline: React.PropTypes.bool,
+        atEndOfLiveTimeline: PropTypes.bool,
 
         // This is true when the user is alone in the room, but has also sent a message.
         // Used to suggest to the user to invite someone
-        sentMessageAndIsAlone: React.PropTypes.bool,
+        sentMessageAndIsAlone: PropTypes.bool,
 
         // true if there is an active call in this room (means we show
         // the 'Active Call' text in the status bar if there is nothing
         // more interesting)
-        hasActiveCall: React.PropTypes.bool,
+        hasActiveCall: PropTypes.bool,
 
         // Number of names to display in typing indication. E.g. set to 3, will
         // result in "X, Y, Z and 100 others are typing."
-        whoIsTypingLimit: React.PropTypes.number,
+        whoIsTypingLimit: PropTypes.number,
 
         // callback for when the user clicks on the 'resend all' button in the
         // 'unsent messages' bar
-        onResendAllClick: React.PropTypes.func,
+        onResendAllClick: PropTypes.func,
 
         // callback for when the user clicks on the 'cancel all' button in the
         // 'unsent messages' bar
-        onCancelAllClick: React.PropTypes.func,
+        onCancelAllClick: PropTypes.func,
 
         // callback for when the user clicks on the 'invite others' button in the
         // 'you are alone' bar
-        onInviteClick: React.PropTypes.func,
+        onInviteClick: PropTypes.func,
 
         // callback for when the user clicks on the 'stop warning me' button in the
         // 'you are alone' bar
-        onStopWarningClick: React.PropTypes.func,
+        onStopWarningClick: PropTypes.func,
 
         // callback for when the user clicks on the 'scroll to bottom' button
-        onScrollToBottomClick: React.PropTypes.func,
+        onScrollToBottomClick: PropTypes.func,
 
         // callback for when we do something that changes the size of the
         // status bar. This is used to trigger a re-layout in the parent
         // component.
-        onResize: React.PropTypes.func,
+        onResize: PropTypes.func,
 
         // callback for when the status bar can be hidden from view, as it is
         // not displaying anything
-        onHidden: React.PropTypes.func,
+        onHidden: PropTypes.func,
 
         // callback for when the status bar is displaying something and should
         // be visible
-        onVisible: React.PropTypes.func,
+        onVisible: PropTypes.func,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js
index e240ab38d5..0bc825f076 100644
--- a/src/components/structures/RoomView.js
+++ b/src/components/structures/RoomView.js
@@ -24,6 +24,7 @@ import shouldHideEvent from "../../shouldHideEvent";
 
 const React = require("react");
 const ReactDOM = require("react-dom");
+import PropTypes from 'prop-types';
 import Promise from 'bluebird';
 const classNames = require("classnames");
 import { _t } from '../../languageHandler';
@@ -58,18 +59,18 @@ if (DEBUG) {
 module.exports = React.createClass({
     displayName: 'RoomView',
     propTypes: {
-        ConferenceHandler: React.PropTypes.any,
+        ConferenceHandler: PropTypes.any,
 
         // Called with the credentials of a registered user (if they were a ROU that
         // transitioned to PWLU)
-        onRegistered: React.PropTypes.func,
+        onRegistered: PropTypes.func,
 
         // An object representing a third party invite to join this room
         // Fields:
         // * inviteSignUrl (string) The URL used to join this room from an email invite
         //                          (given as part of the link in the invite email)
         // * invitedEmail (string) The email address that was invited to this room
-        thirdPartyInvite: React.PropTypes.object,
+        thirdPartyInvite: PropTypes.object,
 
         // Any data about the room that would normally come from the Home Server
         // but has been passed out-of-band, eg. the room name and avatar URL
@@ -80,10 +81,10 @@ module.exports = React.createClass({
         //  * avatarUrl (string) The mxc:// avatar URL for the room
         //  * inviterName (string) The display name of the person who
         //  *                      invited us tovthe room
-        oobData: React.PropTypes.object,
+        oobData: PropTypes.object,
 
         // is the RightPanel collapsed?
-        collapsedRhs: React.PropTypes.bool,
+        collapsedRhs: PropTypes.bool,
     },
 
     getInitialState: function() {
diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js
index 37cb2977aa..cbb6001d5f 100644
--- a/src/components/structures/ScrollPanel.js
+++ b/src/components/structures/ScrollPanel.js
@@ -16,6 +16,7 @@ limitations under the License.
 
 const React = require("react");
 const ReactDOM = require("react-dom");
+import PropTypes from 'prop-types';
 const GeminiScrollbar = require('react-gemini-scrollbar');
 import Promise from 'bluebird';
 import { KeyCode } from '../../Keyboard';
@@ -86,7 +87,7 @@ module.exports = React.createClass({
          * scroll down to show the new element, rather than preserving the
          * existing view.
          */
-        stickyBottom: React.PropTypes.bool,
+        stickyBottom: PropTypes.bool,
 
         /* startAtBottom: if set to true, the view is assumed to start
          * scrolled to the bottom.
@@ -95,7 +96,7 @@ module.exports = React.createClass({
          * behaviour stays the same for other uses of ScrollPanel.
          * If so, let's remove this parameter down the line.
          */
-        startAtBottom: React.PropTypes.bool,
+        startAtBottom: PropTypes.bool,
 
         /* onFillRequest(backwards): a callback which is called on scroll when
          * the user nears the start (backwards = true) or end (backwards =
@@ -110,7 +111,7 @@ module.exports = React.createClass({
          * directon (at this time) - which will stop the pagination cycle until
          * the user scrolls again.
          */
-        onFillRequest: React.PropTypes.func,
+        onFillRequest: PropTypes.func,
 
         /* onUnfillRequest(backwards): a callback which is called on scroll when
          * there are children elements that are far out of view and could be removed
@@ -121,24 +122,24 @@ module.exports = React.createClass({
          * first element to remove if removing from the front/bottom, and last element
          * to remove if removing from the back/top.
          */
-        onUnfillRequest: React.PropTypes.func,
+        onUnfillRequest: PropTypes.func,
 
         /* onScroll: a callback which is called whenever any scroll happens.
          */
-        onScroll: React.PropTypes.func,
+        onScroll: PropTypes.func,
 
         /* onResize: a callback which is called whenever the Gemini scroll
          * panel is resized
          */
-        onResize: React.PropTypes.func,
+        onResize: PropTypes.func,
 
         /* className: classnames to add to the top-level div
          */
-        className: React.PropTypes.string,
+        className: PropTypes.string,
 
         /* style: styles to add to the top-level div
          */
-        style: React.PropTypes.object,
+        style: PropTypes.object,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js
index 98f57a60b5..3760bb37c5 100644
--- a/src/components/structures/TimelinePanel.js
+++ b/src/components/structures/TimelinePanel.js
@@ -19,6 +19,7 @@ import SettingsStore from "../../settings/SettingsStore";
 
 const React = require('react');
 const ReactDOM = require("react-dom");
+import PropTypes from 'prop-types';
 import Promise from 'bluebird';
 
 const Matrix = require("matrix-js-sdk");
@@ -58,49 +59,49 @@ var TimelinePanel = React.createClass({
         // representing.  This may or may not have a room, depending on what it's
         // a timeline representing.  If it has a room, we maintain RRs etc for
         // that room.
-        timelineSet: React.PropTypes.object.isRequired,
+        timelineSet: PropTypes.object.isRequired,
 
-        showReadReceipts: React.PropTypes.bool,
+        showReadReceipts: PropTypes.bool,
         // Enable managing RRs and RMs. These require the timelineSet to have a room.
-        manageReadReceipts: React.PropTypes.bool,
-        manageReadMarkers: React.PropTypes.bool,
+        manageReadReceipts: PropTypes.bool,
+        manageReadMarkers: PropTypes.bool,
 
         // true to give the component a 'display: none' style.
-        hidden: React.PropTypes.bool,
+        hidden: PropTypes.bool,
 
         // ID of an event to highlight. If undefined, no event will be highlighted.
         // typically this will be either 'eventId' or undefined.
-        highlightedEventId: React.PropTypes.string,
+        highlightedEventId: PropTypes.string,
 
         // id of an event to jump to. If not given, will go to the end of the
         // live timeline.
-        eventId: React.PropTypes.string,
+        eventId: PropTypes.string,
 
         // where to position the event given by eventId, in pixels from the
         // bottom of the viewport. If not given, will try to put the event
         // half way down the viewport.
-        eventPixelOffset: React.PropTypes.number,
+        eventPixelOffset: PropTypes.number,
 
         // Should we show URL Previews
-        showUrlPreview: React.PropTypes.bool,
+        showUrlPreview: PropTypes.bool,
 
         // callback which is called when the panel is scrolled.
-        onScroll: React.PropTypes.func,
+        onScroll: PropTypes.func,
 
         // callback which is called when the read-up-to mark is updated.
-        onReadMarkerUpdated: React.PropTypes.func,
+        onReadMarkerUpdated: PropTypes.func,
 
         // maximum number of events to show in a timeline
-        timelineCap: React.PropTypes.number,
+        timelineCap: PropTypes.number,
 
         // classname to use for the messagepanel
-        className: React.PropTypes.string,
+        className: PropTypes.string,
 
         // shape property to be passed to EventTiles
-        tileShape: React.PropTypes.string,
+        tileShape: PropTypes.string,
 
         // placeholder text to use if the timeline is empty
-        empty: React.PropTypes.string,
+        empty: PropTypes.string,
     },
 
     statics: {
diff --git a/src/components/structures/UploadBar.js b/src/components/structures/UploadBar.js
index ca566d3a64..fed4ff33b3 100644
--- a/src/components/structures/UploadBar.js
+++ b/src/components/structures/UploadBar.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const ContentMessages = require('../../ContentMessages');
 const dis = require('../../dispatcher');
 const filesize = require('filesize');
@@ -22,7 +23,7 @@ import { _t } from '../../languageHandler';
 
 module.exports = React.createClass({displayName: 'UploadBar',
     propTypes: {
-        room: React.PropTypes.object,
+        room: PropTypes.object,
     },
 
     componentDidMount: function() {
diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js
index 087b96c509..92cbb6e57e 100644
--- a/src/components/structures/UserSettings.js
+++ b/src/components/structures/UserSettings.js
@@ -19,6 +19,7 @@ import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
 
 const React = require('react');
 const ReactDOM = require('react-dom');
+import PropTypes from 'prop-types';
 const sdk = require('../../index');
 const MatrixClientPeg = require("../../MatrixClientPeg");
 const PlatformPeg = require("../../PlatformPeg");
@@ -125,8 +126,8 @@ const THEMES = [
 
 const IgnoredUser = React.createClass({
     propTypes: {
-        userId: React.PropTypes.string.isRequired,
-        onUnignored: React.PropTypes.func.isRequired,
+        userId: PropTypes.string.isRequired,
+        onUnignored: PropTypes.func.isRequired,
     },
 
     _onUnignoreClick: function() {
@@ -155,16 +156,16 @@ module.exports = React.createClass({
     displayName: 'UserSettings',
 
     propTypes: {
-        onClose: React.PropTypes.func,
+        onClose: PropTypes.func,
         // The brand string given when creating email pushers
-        brand: React.PropTypes.string,
+        brand: PropTypes.string,
 
         // The base URL to use in the referral link. Defaults to window.location.origin.
-        referralBaseUrl: React.PropTypes.string,
+        referralBaseUrl: PropTypes.string,
 
         // Team token for the referral link. If falsy, the referral section will
         // not appear
-        teamToken: React.PropTypes.string,
+        teamToken: PropTypes.string,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/structures/login/ForgotPassword.js b/src/components/structures/login/ForgotPassword.js
index 43753bfd38..53688ee6c3 100644
--- a/src/components/structures/login/ForgotPassword.js
+++ b/src/components/structures/login/ForgotPassword.js
@@ -18,6 +18,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 import sdk from '../../../index';
 import Modal from "../../../Modal";
@@ -29,13 +30,13 @@ module.exports = React.createClass({
     displayName: 'ForgotPassword',
 
     propTypes: {
-        defaultHsUrl: React.PropTypes.string,
-        defaultIsUrl: React.PropTypes.string,
-        customHsUrl: React.PropTypes.string,
-        customIsUrl: React.PropTypes.string,
-        onLoginClick: React.PropTypes.func,
-        onRegisterClick: React.PropTypes.func,
-        onComplete: React.PropTypes.func.isRequired,
+        defaultHsUrl: PropTypes.string,
+        defaultIsUrl: PropTypes.string,
+        customHsUrl: PropTypes.string,
+        customIsUrl: PropTypes.string,
+        onLoginClick: PropTypes.func,
+        onRegisterClick: PropTypes.func,
+        onComplete: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/structures/login/Login.js b/src/components/structures/login/Login.js
index 9ed710534b..f4c08e8362 100644
--- a/src/components/structures/login/Login.js
+++ b/src/components/structures/login/Login.js
@@ -18,6 +18,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 import * as languageHandler from '../../../languageHandler';
 import sdk from '../../../index';
@@ -36,27 +37,27 @@ module.exports = React.createClass({
     displayName: 'Login',
 
     propTypes: {
-        onLoggedIn: React.PropTypes.func.isRequired,
+        onLoggedIn: PropTypes.func.isRequired,
 
-        enableGuest: React.PropTypes.bool,
+        enableGuest: PropTypes.bool,
 
-        customHsUrl: React.PropTypes.string,
-        customIsUrl: React.PropTypes.string,
-        defaultHsUrl: React.PropTypes.string,
-        defaultIsUrl: React.PropTypes.string,
+        customHsUrl: PropTypes.string,
+        customIsUrl: PropTypes.string,
+        defaultHsUrl: PropTypes.string,
+        defaultIsUrl: PropTypes.string,
         // Secondary HS which we try to log into if the user is using
         // the default HS but login fails. Useful for migrating to a
         // different home server without confusing users.
-        fallbackHsUrl: React.PropTypes.string,
+        fallbackHsUrl: PropTypes.string,
 
-        defaultDeviceDisplayName: React.PropTypes.string,
+        defaultDeviceDisplayName: PropTypes.string,
 
         // login shouldn't know or care how registration is done.
-        onRegisterClick: React.PropTypes.func.isRequired,
+        onRegisterClick: PropTypes.func.isRequired,
 
         // login shouldn't care how password recovery is done.
-        onForgotPasswordClick: React.PropTypes.func,
-        onCancelClick: React.PropTypes.func,
+        onForgotPasswordClick: PropTypes.func,
+        onCancelClick: PropTypes.func,
     },
 
     getInitialState: function() {
diff --git a/src/components/structures/login/PostRegistration.js b/src/components/structures/login/PostRegistration.js
index 184356e852..f6165348bd 100644
--- a/src/components/structures/login/PostRegistration.js
+++ b/src/components/structures/login/PostRegistration.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { _t } from '../../../languageHandler';
@@ -25,7 +26,7 @@ module.exports = React.createClass({
     displayName: 'PostRegistration',
 
     propTypes: {
-        onComplete: React.PropTypes.func.isRequired,
+        onComplete: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/structures/login/Registration.js b/src/components/structures/login/Registration.js
index e57b7fd0c2..b8a85c5f82 100644
--- a/src/components/structures/login/Registration.js
+++ b/src/components/structures/login/Registration.js
@@ -19,6 +19,7 @@ import Matrix from 'matrix-js-sdk';
 
 import Promise from 'bluebird';
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import sdk from '../../../index';
 import ServerConfig from '../../views/login/ServerConfig';
@@ -35,31 +36,31 @@ module.exports = React.createClass({
     displayName: 'Registration',
 
     propTypes: {
-        onLoggedIn: React.PropTypes.func.isRequired,
-        clientSecret: React.PropTypes.string,
-        sessionId: React.PropTypes.string,
-        makeRegistrationUrl: React.PropTypes.func.isRequired,
-        idSid: React.PropTypes.string,
-        customHsUrl: React.PropTypes.string,
-        customIsUrl: React.PropTypes.string,
-        defaultHsUrl: React.PropTypes.string,
-        defaultIsUrl: React.PropTypes.string,
-        brand: React.PropTypes.string,
-        email: React.PropTypes.string,
-        referrer: React.PropTypes.string,
-        teamServerConfig: React.PropTypes.shape({
+        onLoggedIn: PropTypes.func.isRequired,
+        clientSecret: PropTypes.string,
+        sessionId: PropTypes.string,
+        makeRegistrationUrl: PropTypes.func.isRequired,
+        idSid: PropTypes.string,
+        customHsUrl: PropTypes.string,
+        customIsUrl: PropTypes.string,
+        defaultHsUrl: PropTypes.string,
+        defaultIsUrl: PropTypes.string,
+        brand: PropTypes.string,
+        email: PropTypes.string,
+        referrer: PropTypes.string,
+        teamServerConfig: PropTypes.shape({
             // Email address to request new teams
-            supportEmail: React.PropTypes.string.isRequired,
+            supportEmail: PropTypes.string.isRequired,
             // URL of the riot-team-server to get team configurations and track referrals
-            teamServerURL: React.PropTypes.string.isRequired,
+            teamServerURL: PropTypes.string.isRequired,
         }),
-        teamSelected: React.PropTypes.object,
+        teamSelected: PropTypes.object,
 
-        defaultDeviceDisplayName: React.PropTypes.string,
+        defaultDeviceDisplayName: PropTypes.string,
 
         // registration shouldn't know or care how login is done.
-        onLoginClick: React.PropTypes.func.isRequired,
-        onCancelClick: React.PropTypes.func,
+        onLoginClick: PropTypes.func.isRequired,
+        onCancelClick: PropTypes.func,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/avatars/BaseAvatar.js b/src/components/views/avatars/BaseAvatar.js
index f68e98ec3d..47c217eb96 100644
--- a/src/components/views/avatars/BaseAvatar.js
+++ b/src/components/views/avatars/BaseAvatar.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import AvatarLogic from '../../../Avatar';
 import sdk from '../../../index';
 import AccessibleButton from '../elements/AccessibleButton';
@@ -23,16 +24,16 @@ module.exports = React.createClass({
     displayName: 'BaseAvatar',
 
     propTypes: {
-        name: React.PropTypes.string.isRequired, // The name (first initial used as default)
-        idName: React.PropTypes.string, // ID for generating hash colours
-        title: React.PropTypes.string, // onHover title text
-        url: React.PropTypes.string, // highest priority of them all, shortcut to set in urls[0]
-        urls: React.PropTypes.array, // [highest_priority, ... , lowest_priority]
-        width: React.PropTypes.number,
-        height: React.PropTypes.number,
+        name: PropTypes.string.isRequired, // The name (first initial used as default)
+        idName: PropTypes.string, // ID for generating hash colours
+        title: PropTypes.string, // onHover title text
+        url: PropTypes.string, // highest priority of them all, shortcut to set in urls[0]
+        urls: PropTypes.array, // [highest_priority, ... , lowest_priority]
+        width: PropTypes.number,
+        height: PropTypes.number,
         // XXX resizeMethod not actually used.
-        resizeMethod: React.PropTypes.string,
-        defaultToInitialLetter: React.PropTypes.bool, // true to add default url
+        resizeMethod: PropTypes.string,
+        defaultToInitialLetter: PropTypes.bool, // true to add default url
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/avatars/MemberAvatar.js b/src/components/views/avatars/MemberAvatar.js
index 89047cd69c..a4fe5e280f 100644
--- a/src/components/views/avatars/MemberAvatar.js
+++ b/src/components/views/avatars/MemberAvatar.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const Avatar = require('../../../Avatar');
 const sdk = require("../../../index");
 const dispatcher = require("../../../dispatcher");
@@ -25,15 +26,15 @@ module.exports = React.createClass({
     displayName: 'MemberAvatar',
 
     propTypes: {
-        member: React.PropTypes.object.isRequired,
-        width: React.PropTypes.number,
-        height: React.PropTypes.number,
-        resizeMethod: React.PropTypes.string,
+        member: PropTypes.object.isRequired,
+        width: PropTypes.number,
+        height: PropTypes.number,
+        resizeMethod: PropTypes.string,
         // The onClick to give the avatar
-        onClick: React.PropTypes.func,
+        onClick: PropTypes.func,
         // Whether the onClick of the avatar should be overriden to dispatch 'view_user'
-        viewUserOnClick: React.PropTypes.bool,
-        title: React.PropTypes.string,
+        viewUserOnClick: PropTypes.bool,
+        title: PropTypes.string,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/avatars/MemberPresenceAvatar.js b/src/components/views/avatars/MemberPresenceAvatar.js
index 49cfee2cff..aa6def00ae 100644
--- a/src/components/views/avatars/MemberPresenceAvatar.js
+++ b/src/components/views/avatars/MemberPresenceAvatar.js
@@ -17,6 +17,7 @@
 'use strict';
 
 import React from "react";
+import PropTypes from 'prop-types';
 import * as sdk from "../../../index";
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import AccessibleButton from '../elements/AccessibleButton';
@@ -30,10 +31,10 @@ module.exports = React.createClass({
     displayName: 'MemberPresenceAvatar',
 
     propTypes: {
-        member: React.PropTypes.object.isRequired,
-        width: React.PropTypes.number,
-        height: React.PropTypes.number,
-        resizeMethod: React.PropTypes.string,
+        member: PropTypes.object.isRequired,
+        width: PropTypes.number,
+        height: PropTypes.number,
+        resizeMethod: PropTypes.string,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/avatars/RoomAvatar.js b/src/components/views/avatars/RoomAvatar.js
index 11554b2379..cae02ac408 100644
--- a/src/components/views/avatars/RoomAvatar.js
+++ b/src/components/views/avatars/RoomAvatar.js
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 import React from "react";
+import PropTypes from 'prop-types';
 import {ContentRepo} from "matrix-js-sdk";
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import sdk from "../../../index";
@@ -25,11 +26,11 @@ module.exports = React.createClass({
     // oobData.avatarUrl should be set (else there
     // would be nowhere to get the avatar from)
     propTypes: {
-        room: React.PropTypes.object,
-        oobData: React.PropTypes.object,
-        width: React.PropTypes.number,
-        height: React.PropTypes.number,
-        resizeMethod: React.PropTypes.string,
+        room: PropTypes.object,
+        oobData: PropTypes.object,
+        width: PropTypes.number,
+        height: PropTypes.number,
+        resizeMethod: PropTypes.string,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/create_room/CreateRoomButton.js b/src/components/views/create_room/CreateRoomButton.js
index 8a5f00d942..25f71f542d 100644
--- a/src/components/views/create_room/CreateRoomButton.js
+++ b/src/components/views/create_room/CreateRoomButton.js
@@ -17,11 +17,12 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 module.exports = React.createClass({
     displayName: 'CreateRoomButton',
     propTypes: {
-        onCreateRoom: React.PropTypes.func,
+        onCreateRoom: PropTypes.func,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/create_room/Presets.js b/src/components/views/create_room/Presets.js
index 2073896d87..c9607c0082 100644
--- a/src/components/views/create_room/Presets.js
+++ b/src/components/views/create_room/Presets.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
 const Presets = {
@@ -28,8 +29,8 @@ const Presets = {
 module.exports = React.createClass({
     displayName: 'CreateRoomPresets',
     propTypes: {
-        onChange: React.PropTypes.func,
-        preset: React.PropTypes.string,
+        onChange: PropTypes.func,
+        preset: PropTypes.string,
     },
 
     Presets: Presets,
diff --git a/src/components/views/create_room/RoomAlias.js b/src/components/views/create_room/RoomAlias.js
index d4228a8bca..6262db7833 100644
--- a/src/components/views/create_room/RoomAlias.js
+++ b/src/components/views/create_room/RoomAlias.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 const React = require('react');
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
 module.exports = React.createClass({
@@ -22,9 +23,9 @@ module.exports = React.createClass({
     propTypes: {
         // Specifying a homeserver will make magical things happen when you,
         // e.g. start typing in the room alias box.
-        homeserver: React.PropTypes.string,
-        alias: React.PropTypes.string,
-        onChange: React.PropTypes.func,
+        homeserver: PropTypes.string,
+        alias: PropTypes.string,
+        onChange: PropTypes.func,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js
index b88a6c026e..518d29aa8c 100644
--- a/src/components/views/dialogs/BaseDialog.js
+++ b/src/components/views/dialogs/BaseDialog.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import { KeyCode } from '../../../Keyboard';
 import AccessibleButton from '../elements/AccessibleButton';
@@ -31,20 +32,20 @@ export default React.createClass({
 
     propTypes: {
         // onFinished callback to call when Escape is pressed
-        onFinished: React.PropTypes.func.isRequired,
+        onFinished: PropTypes.func.isRequired,
 
         // callback to call when Enter is pressed
-        onEnterPressed: React.PropTypes.func,
+        onEnterPressed: PropTypes.func,
 
         // CSS class to apply to dialog div
-        className: React.PropTypes.string,
+        className: PropTypes.string,
 
         // Title for the dialog.
         // (could probably actually be something more complicated than a string if desired)
-        title: React.PropTypes.string.isRequired,
+        title: PropTypes.string.isRequired,
 
         // children should be the content of the dialog
-        children: React.PropTypes.node,
+        children: PropTypes.node,
     },
 
     _onKeyDown: function(e) {
diff --git a/src/components/views/dialogs/ChatCreateOrReuseDialog.js b/src/components/views/dialogs/ChatCreateOrReuseDialog.js
index e0578f3b53..ef21db7ecb 100644
--- a/src/components/views/dialogs/ChatCreateOrReuseDialog.js
+++ b/src/components/views/dialogs/ChatCreateOrReuseDialog.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
@@ -187,9 +188,9 @@ export default class ChatCreateOrReuseDialog extends React.Component {
 }
 
 ChatCreateOrReuseDialog.propTyps = {
-    userId: React.PropTypes.string.isRequired,
+    userId: PropTypes.string.isRequired,
     // Called when clicking outside of the dialog
-    onFinished: React.PropTypes.func.isRequired,
-    onNewDMClick: React.PropTypes.func.isRequired,
-    onExistingRoomSelected: React.PropTypes.func.isRequired,
+    onFinished: PropTypes.func.isRequired,
+    onNewDMClick: PropTypes.func.isRequired,
+    onExistingRoomSelected: PropTypes.func.isRequired,
 };
diff --git a/src/components/views/dialogs/ConfirmUserActionDialog.js b/src/components/views/dialogs/ConfirmUserActionDialog.js
index 78d084b709..39e1f66f96 100644
--- a/src/components/views/dialogs/ConfirmUserActionDialog.js
+++ b/src/components/views/dialogs/ConfirmUserActionDialog.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import { MatrixClient } from 'matrix-js-sdk';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
@@ -33,20 +34,20 @@ export default React.createClass({
     displayName: 'ConfirmUserActionDialog',
     propTypes: {
         // matrix-js-sdk (room) member object. Supply either this or 'groupMember'
-        member: React.PropTypes.object,
+        member: PropTypes.object,
         // group member object. Supply either this or 'member'
         groupMember: GroupMemberType,
         // needed if a group member is specified
-        matrixClient: React.PropTypes.instanceOf(MatrixClient),
-        action: React.PropTypes.string.isRequired, // eg. 'Ban'
-        title: React.PropTypes.string.isRequired, // eg. 'Ban this user?'
+        matrixClient: PropTypes.instanceOf(MatrixClient),
+        action: PropTypes.string.isRequired, // eg. 'Ban'
+        title: PropTypes.string.isRequired, // eg. 'Ban this user?'
 
         // Whether to display a text field for a reason
         // If true, the second argument to onFinished will
         // be the string entered.
-        askReason: React.PropTypes.bool,
-        danger: React.PropTypes.bool,
-        onFinished: React.PropTypes.func.isRequired,
+        askReason: PropTypes.bool,
+        danger: PropTypes.bool,
+        onFinished: PropTypes.func.isRequired,
     },
 
     defaultProps: {
diff --git a/src/components/views/dialogs/CreateRoomDialog.js b/src/components/views/dialogs/CreateRoomDialog.js
index f7be47b3eb..366c5ac678 100644
--- a/src/components/views/dialogs/CreateRoomDialog.js
+++ b/src/components/views/dialogs/CreateRoomDialog.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import SdkConfig from '../../../SdkConfig';
 import { _t } from '../../../languageHandler';
@@ -22,7 +23,7 @@ import { _t } from '../../../languageHandler';
 export default React.createClass({
     displayName: 'CreateRoomDialog',
     propTypes: {
-        onFinished: React.PropTypes.func.isRequired,
+        onFinished: PropTypes.func.isRequired,
     },
 
     componentDidMount: function() {
diff --git a/src/components/views/dialogs/DeactivateAccountDialog.js b/src/components/views/dialogs/DeactivateAccountDialog.js
index c45e072d72..7d850fce2b 100644
--- a/src/components/views/dialogs/DeactivateAccountDialog.js
+++ b/src/components/views/dialogs/DeactivateAccountDialog.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import sdk from '../../../index';
 import Analytics from '../../../Analytics';
@@ -136,5 +137,5 @@ export default class DeactivateAccountDialog extends React.Component {
 }
 
 DeactivateAccountDialog.propTypes = {
-    onFinished: React.PropTypes.func.isRequired,
+    onFinished: PropTypes.func.isRequired,
 };
diff --git a/src/components/views/dialogs/DeviceVerifyDialog.js b/src/components/views/dialogs/DeviceVerifyDialog.js
index ba31d2a8c2..6bec933389 100644
--- a/src/components/views/dialogs/DeviceVerifyDialog.js
+++ b/src/components/views/dialogs/DeviceVerifyDialog.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import sdk from '../../../index';
 import * as FormattingUtils from '../../../utils/FormattingUtils';
@@ -71,7 +72,7 @@ export default function DeviceVerifyDialog(props) {
 }
 
 DeviceVerifyDialog.propTypes = {
-    userId: React.PropTypes.string.isRequired,
-    device: React.PropTypes.object.isRequired,
-    onFinished: React.PropTypes.func.isRequired,
+    userId: PropTypes.string.isRequired,
+    device: PropTypes.object.isRequired,
+    onFinished: PropTypes.func.isRequired,
 };
diff --git a/src/components/views/dialogs/ErrorDialog.js b/src/components/views/dialogs/ErrorDialog.js
index 97ed47e10f..2af2d6214f 100644
--- a/src/components/views/dialogs/ErrorDialog.js
+++ b/src/components/views/dialogs/ErrorDialog.js
@@ -26,20 +26,21 @@ limitations under the License.
  */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 export default React.createClass({
     displayName: 'ErrorDialog',
     propTypes: {
-        title: React.PropTypes.string,
-        description: React.PropTypes.oneOfType([
-            React.PropTypes.element,
-            React.PropTypes.string,
+        title: PropTypes.string,
+        description: PropTypes.oneOfType([
+            PropTypes.element,
+            PropTypes.string,
         ]),
-        button: React.PropTypes.string,
-        focus: React.PropTypes.bool,
-        onFinished: React.PropTypes.func.isRequired,
+        button: PropTypes.string,
+        focus: PropTypes.bool,
+        onFinished: PropTypes.func.isRequired,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/dialogs/InteractiveAuthDialog.js b/src/components/views/dialogs/InteractiveAuthDialog.js
index 59de7c7f59..a47702305c 100644
--- a/src/components/views/dialogs/InteractiveAuthDialog.js
+++ b/src/components/views/dialogs/InteractiveAuthDialog.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
@@ -27,22 +28,22 @@ export default React.createClass({
 
     propTypes: {
         // matrix client to use for UI auth requests
-        matrixClient: React.PropTypes.object.isRequired,
+        matrixClient: PropTypes.object.isRequired,
 
         // response from initial request. If not supplied, will do a request on
         // mount.
-        authData: React.PropTypes.shape({
-            flows: React.PropTypes.array,
-            params: React.PropTypes.object,
-            session: React.PropTypes.string,
+        authData: PropTypes.shape({
+            flows: PropTypes.array,
+            params: PropTypes.object,
+            session: PropTypes.string,
         }),
 
         // callback
-        makeRequest: React.PropTypes.func.isRequired,
+        makeRequest: PropTypes.func.isRequired,
 
-        onFinished: React.PropTypes.func.isRequired,
+        onFinished: PropTypes.func.isRequired,
 
-        title: React.PropTypes.string,
+        title: PropTypes.string,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/dialogs/KeyShareDialog.js b/src/components/views/dialogs/KeyShareDialog.js
index 9c8be27c89..00bcc942a1 100644
--- a/src/components/views/dialogs/KeyShareDialog.js
+++ b/src/components/views/dialogs/KeyShareDialog.js
@@ -16,6 +16,7 @@ limitations under the License.
 
 import Modal from '../../../Modal';
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 
 import { _t, _td } from '../../../languageHandler';
@@ -30,10 +31,10 @@ import { _t, _td } from '../../../languageHandler';
  */
 export default React.createClass({
     propTypes: {
-        matrixClient: React.PropTypes.object.isRequired,
-        userId: React.PropTypes.string.isRequired,
-        deviceId: React.PropTypes.string.isRequired,
-        onFinished: React.PropTypes.func.isRequired,
+        matrixClient: PropTypes.object.isRequired,
+        userId: PropTypes.string.isRequired,
+        deviceId: PropTypes.string.isRequired,
+        onFinished: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/dialogs/QuestionDialog.js b/src/components/views/dialogs/QuestionDialog.js
index 339b284e2f..719f372cfe 100644
--- a/src/components/views/dialogs/QuestionDialog.js
+++ b/src/components/views/dialogs/QuestionDialog.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 import classnames from 'classnames';
@@ -23,13 +24,13 @@ import classnames from 'classnames';
 export default React.createClass({
     displayName: 'QuestionDialog',
     propTypes: {
-        title: React.PropTypes.string,
-        description: React.PropTypes.node,
-        extraButtons: React.PropTypes.node,
-        button: React.PropTypes.string,
-        danger: React.PropTypes.bool,
-        focus: React.PropTypes.bool,
-        onFinished: React.PropTypes.func.isRequired,
+        title: PropTypes.string,
+        description: PropTypes.node,
+        extraButtons: PropTypes.node,
+        button: PropTypes.string,
+        danger: PropTypes.bool,
+        focus: PropTypes.bool,
+        onFinished: PropTypes.func.isRequired,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.js
index 75ae0eda17..63b9c64530 100644
--- a/src/components/views/dialogs/SessionRestoreErrorDialog.js
+++ b/src/components/views/dialogs/SessionRestoreErrorDialog.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import SdkConfig from '../../../SdkConfig';
 import Modal from '../../../Modal';
@@ -25,8 +26,8 @@ export default React.createClass({
     displayName: 'SessionRestoreErrorDialog',
 
     propTypes: {
-        error: React.PropTypes.string.isRequired,
-        onFinished: React.PropTypes.func.isRequired,
+        error: PropTypes.string.isRequired,
+        onFinished: PropTypes.func.isRequired,
     },
 
     _sendBugReport: function() {
diff --git a/src/components/views/dialogs/SetEmailDialog.js b/src/components/views/dialogs/SetEmailDialog.js
index 2dd996953d..c00cc1122b 100644
--- a/src/components/views/dialogs/SetEmailDialog.js
+++ b/src/components/views/dialogs/SetEmailDialog.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import Email from '../../../email';
 import AddThreepid from '../../../AddThreepid';
@@ -30,7 +31,7 @@ import Modal from '../../../Modal';
 export default React.createClass({
     displayName: 'SetEmailDialog',
     propTypes: {
-        onFinished: React.PropTypes.func.isRequired,
+        onFinished: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/dialogs/SetMxIdDialog.js b/src/components/views/dialogs/SetMxIdDialog.js
index 3ffafb0659..6ebc2eb87f 100644
--- a/src/components/views/dialogs/SetMxIdDialog.js
+++ b/src/components/views/dialogs/SetMxIdDialog.js
@@ -17,6 +17,7 @@ limitations under the License.
 
 import Promise from 'bluebird';
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import classnames from 'classnames';
@@ -35,11 +36,11 @@ const USERNAME_CHECK_DEBOUNCE_MS = 250;
 export default React.createClass({
     displayName: 'SetMxIdDialog',
     propTypes: {
-        onFinished: React.PropTypes.func.isRequired,
+        onFinished: PropTypes.func.isRequired,
         // Called when the user requests to register with a different homeserver
-        onDifferentServerClicked: React.PropTypes.func.isRequired,
+        onDifferentServerClicked: PropTypes.func.isRequired,
         // Called if the user wants to switch to login instead
-        onLoginClick: React.PropTypes.func.isRequired,
+        onLoginClick: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/dialogs/TextInputDialog.js b/src/components/views/dialogs/TextInputDialog.js
index 5ea4191e5e..d45e70c043 100644
--- a/src/components/views/dialogs/TextInputDialog.js
+++ b/src/components/views/dialogs/TextInputDialog.js
@@ -15,21 +15,22 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
 export default React.createClass({
     displayName: 'TextInputDialog',
     propTypes: {
-        title: React.PropTypes.string,
-        description: React.PropTypes.oneOfType([
-            React.PropTypes.element,
-            React.PropTypes.string,
+        title: PropTypes.string,
+        description: PropTypes.oneOfType([
+            PropTypes.element,
+            PropTypes.string,
         ]),
-        value: React.PropTypes.string,
-        button: React.PropTypes.string,
-        focus: React.PropTypes.bool,
-        onFinished: React.PropTypes.func.isRequired,
+        value: PropTypes.string,
+        button: PropTypes.string,
+        focus: PropTypes.bool,
+        onFinished: PropTypes.func.isRequired,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/elements/AccessibleButton.js b/src/components/views/elements/AccessibleButton.js
index 794e0a4dd7..c6a973270a 100644
--- a/src/components/views/elements/AccessibleButton.js
+++ b/src/components/views/elements/AccessibleButton.js
@@ -15,6 +15,7 @@
  */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 /**
  * AccessibleButton is a generic wrapper for any element that should be treated
@@ -44,9 +45,9 @@ export default function AccessibleButton(props) {
  *           implemented exactly like a normal onClick handler.
  */
 AccessibleButton.propTypes = {
-    children: React.PropTypes.node,
-    element: React.PropTypes.string,
-    onClick: React.PropTypes.func.isRequired,
+    children: PropTypes.node,
+    element: PropTypes.string,
+    onClick: PropTypes.func.isRequired,
 };
 
 AccessibleButton.defaultProps = {
diff --git a/src/components/views/elements/AddressSelector.js b/src/components/views/elements/AddressSelector.js
index 9330206a39..b4279c7f70 100644
--- a/src/components/views/elements/AddressSelector.js
+++ b/src/components/views/elements/AddressSelector.js
@@ -18,6 +18,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import classNames from 'classnames';
 import { UserAddressType } from '../../../UserAddress';
@@ -26,17 +27,17 @@ export default React.createClass({
     displayName: 'AddressSelector',
 
     propTypes: {
-        onSelected: React.PropTypes.func.isRequired,
+        onSelected: PropTypes.func.isRequired,
 
         // List of the addresses to display
-        addressList: React.PropTypes.arrayOf(UserAddressType).isRequired,
+        addressList: PropTypes.arrayOf(UserAddressType).isRequired,
         // Whether to show the address on the address tiles
-        showAddress: React.PropTypes.bool,
-        truncateAt: React.PropTypes.number.isRequired,
-        selected: React.PropTypes.number,
+        showAddress: PropTypes.bool,
+        truncateAt: PropTypes.number.isRequired,
+        selected: PropTypes.number,
 
         // Element to put as a header on top of the list
-        header: React.PropTypes.node,
+        header: PropTypes.node,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/elements/AddressTile.js b/src/components/views/elements/AddressTile.js
index c8ea4062b1..16e340756a 100644
--- a/src/components/views/elements/AddressTile.js
+++ b/src/components/views/elements/AddressTile.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import sdk from "../../../index";
 import MatrixClientPeg from "../../../MatrixClientPeg";
@@ -28,9 +29,9 @@ export default React.createClass({
 
     propTypes: {
         address: UserAddressType.isRequired,
-        canDismiss: React.PropTypes.bool,
-        onDismissed: React.PropTypes.func,
-        justified: React.PropTypes.bool,
+        canDismiss: PropTypes.bool,
+        onDismissed: PropTypes.func,
+        justified: PropTypes.bool,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js
index 0d67b4c814..a63823555f 100644
--- a/src/components/views/elements/AppTile.js
+++ b/src/components/views/elements/AppTile.js
@@ -19,6 +19,7 @@ limitations under the License.
 import url from 'url';
 import qs from 'querystring';
 import React from 'react';
+import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import PlatformPeg from '../../../PlatformPeg';
 import ScalarAuthClient from '../../../ScalarAuthClient';
@@ -40,19 +41,19 @@ export default React.createClass({
     displayName: 'AppTile',
 
     propTypes: {
-        id: React.PropTypes.string.isRequired,
-        url: React.PropTypes.string.isRequired,
-        name: React.PropTypes.string.isRequired,
-        room: React.PropTypes.object.isRequired,
-        type: React.PropTypes.string.isRequired,
+        id: PropTypes.string.isRequired,
+        url: PropTypes.string.isRequired,
+        name: PropTypes.string.isRequired,
+        room: PropTypes.object.isRequired,
+        type: PropTypes.string.isRequired,
         // Specifying 'fullWidth' as true will render the app tile to fill the width of the app drawer continer.
         // This should be set to true when there is only one widget in the app drawer, otherwise it should be false.
-        fullWidth: React.PropTypes.bool,
+        fullWidth: PropTypes.bool,
         // UserId of the current user
-        userId: React.PropTypes.string.isRequired,
+        userId: PropTypes.string.isRequired,
         // UserId of the entity that added / modified the widget
-        creatorUserId: React.PropTypes.string,
-        waitForIframeLoad: React.PropTypes.bool,
+        creatorUserId: PropTypes.string,
+        waitForIframeLoad: PropTypes.bool,
     },
 
     getDefaultProps() {
diff --git a/src/components/views/elements/DeviceVerifyButtons.js b/src/components/views/elements/DeviceVerifyButtons.js
index bb89efaa30..c775cba610 100644
--- a/src/components/views/elements/DeviceVerifyButtons.js
+++ b/src/components/views/elements/DeviceVerifyButtons.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import sdk from '../../../index';
 import Modal from '../../../Modal';
@@ -24,8 +25,8 @@ export default React.createClass({
     displayName: 'DeviceVerifyButtons',
 
     propTypes: {
-        userId: React.PropTypes.string.isRequired,
-        device: React.PropTypes.object.isRequired,
+        userId: PropTypes.string.isRequired,
+        device: PropTypes.object.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/elements/DirectorySearchBox.js b/src/components/views/elements/DirectorySearchBox.js
index 7132162d5c..14f79687e1 100644
--- a/src/components/views/elements/DirectorySearchBox.js
+++ b/src/components/views/elements/DirectorySearchBox.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import classnames from 'classnames';
 
 export default class DirectorySearchBox extends React.Component {
@@ -105,10 +106,10 @@ export default class DirectorySearchBox extends React.Component {
 }
 
 DirectorySearchBox.propTypes = {
-    className: React.PropTypes.string,
-    onChange: React.PropTypes.func,
-    onClear: React.PropTypes.func,
-    onJoinClick: React.PropTypes.func,
-    placeholder: React.PropTypes.string,
-    showJoinButton: React.PropTypes.bool,
+    className: PropTypes.string,
+    onChange: PropTypes.func,
+    onClear: PropTypes.func,
+    onJoinClick: PropTypes.func,
+    placeholder: PropTypes.string,
+    showJoinButton: PropTypes.bool,
 };
diff --git a/src/components/views/elements/Dropdown.js b/src/components/views/elements/Dropdown.js
index b1291710b7..10111e415e 100644
--- a/src/components/views/elements/Dropdown.js
+++ b/src/components/views/elements/Dropdown.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import classnames from 'classnames';
 import AccessibleButton from './AccessibleButton';
 import { _t } from '../../../languageHandler';
@@ -56,14 +57,14 @@ class MenuOption extends React.Component {
 }
 
 MenuOption.propTypes = {
-    children: React.PropTypes.oneOfType([
-      React.PropTypes.arrayOf(React.PropTypes.node),
-      React.PropTypes.node,
+    children: PropTypes.oneOfType([
+      PropTypes.arrayOf(React.PropTypes.node),
+      PropTypes.node,
     ]),
-    highlighted: React.PropTypes.bool,
-    dropdownKey: React.PropTypes.string,
-    onClick: React.PropTypes.func.isRequired,
-    onMouseEnter: React.PropTypes.func.isRequired,
+    highlighted: PropTypes.bool,
+    dropdownKey: PropTypes.string,
+    onClick: PropTypes.func.isRequired,
+    onMouseEnter: PropTypes.func.isRequired,
 };
 
 /*
@@ -322,20 +323,20 @@ Dropdown.propTypes = {
     // The width that the dropdown should be. If specified,
     // the dropped-down part of the menu will be set to this
     // width.
-    menuWidth: React.PropTypes.number,
+    menuWidth: PropTypes.number,
     // Called when the selected option changes
-    onOptionChange: React.PropTypes.func.isRequired,
+    onOptionChange: PropTypes.func.isRequired,
     // Called when the value of the search field changes
-    onSearchChange: React.PropTypes.func,
-    searchEnabled: React.PropTypes.bool,
+    onSearchChange: PropTypes.func,
+    searchEnabled: PropTypes.bool,
     // Function that, given the key of an option, returns
     // a node representing that option to be displayed in the
     // box itself as the currently-selected option (ie. as
     // opposed to in the actual dropped-down part). If
     // unspecified, the appropriate child element is used as
     // in the dropped-down menu.
-    getShortOption: React.PropTypes.func,
-    value: React.PropTypes.string,
+    getShortOption: PropTypes.func,
+    value: PropTypes.string,
     // negative for consistency with HTML
-    disabled: React.PropTypes.bool,
+    disabled: PropTypes.bool,
 };
diff --git a/src/components/views/elements/EditableText.js b/src/components/views/elements/EditableText.js
index ac8821a0c2..ce1817c272 100644
--- a/src/components/views/elements/EditableText.js
+++ b/src/components/views/elements/EditableText.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 
 const KEY_TAB = 9;
 const KEY_SHIFT = 16;
@@ -26,18 +27,18 @@ module.exports = React.createClass({
     displayName: 'EditableText',
 
     propTypes: {
-        onValueChanged: React.PropTypes.func,
-        initialValue: React.PropTypes.string,
-        label: React.PropTypes.string,
-        placeholder: React.PropTypes.string,
-        className: React.PropTypes.string,
-        labelClassName: React.PropTypes.string,
-        placeholderClassName: React.PropTypes.string,
+        onValueChanged: PropTypes.func,
+        initialValue: PropTypes.string,
+        label: PropTypes.string,
+        placeholder: PropTypes.string,
+        className: PropTypes.string,
+        labelClassName: PropTypes.string,
+        placeholderClassName: PropTypes.string,
         // Overrides blurToSubmit if true
-        blurToCancel: React.PropTypes.bool,
+        blurToCancel: PropTypes.bool,
         // Will cause onValueChanged(value, true) to fire on blur
-        blurToSubmit: React.PropTypes.bool,
-        editable: React.PropTypes.bool,
+        blurToSubmit: PropTypes.bool,
+        editable: PropTypes.bool,
     },
 
     Phases: {
diff --git a/src/components/views/elements/EditableTextContainer.js b/src/components/views/elements/EditableTextContainer.js
index 0025862967..064d2f1c39 100644
--- a/src/components/views/elements/EditableTextContainer.js
+++ b/src/components/views/elements/EditableTextContainer.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import Promise from 'bluebird';
 
@@ -126,21 +127,21 @@ export default class EditableTextContainer extends React.Component {
 
 EditableTextContainer.propTypes = {
     /* callback to retrieve the initial value. */
-    getInitialValue: React.PropTypes.func,
+    getInitialValue: PropTypes.func,
 
     /* initial value; used if getInitialValue is not given */
-    initialValue: React.PropTypes.string,
+    initialValue: PropTypes.string,
 
     /* placeholder text to use when the value is empty (and not being
      * edited) */
-    placeholder: React.PropTypes.string,
+    placeholder: PropTypes.string,
 
     /* callback to update the value. Called with a single argument: the new
      * value. */
-    onSubmit: React.PropTypes.func,
+    onSubmit: PropTypes.func,
 
     /* should the input submit when focus is lost? */
-    blurToSubmit: React.PropTypes.bool,
+    blurToSubmit: PropTypes.bool,
 };
 
 
diff --git a/src/components/views/elements/EmojiText.js b/src/components/views/elements/EmojiText.js
index faab0241ae..9fb650b2c3 100644
--- a/src/components/views/elements/EmojiText.js
+++ b/src/components/views/elements/EmojiText.js
@@ -16,6 +16,7 @@
  */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import {emojifyText, containsEmoji} from '../../../HtmlUtils';
 
 export default function EmojiText(props) {
@@ -32,8 +33,8 @@ export default function EmojiText(props) {
 }
 
 EmojiText.propTypes = {
-    element: React.PropTypes.string,
-    children: React.PropTypes.string.isRequired,
+    element: PropTypes.string,
+    children: PropTypes.string.isRequired,
 };
 
 EmojiText.defaultProps = {
diff --git a/src/components/views/elements/Flair.js b/src/components/views/elements/Flair.js
index 25a8d538e1..a487395a87 100644
--- a/src/components/views/elements/Flair.js
+++ b/src/components/views/elements/Flair.js
@@ -63,7 +63,7 @@ FlairAvatar.propTypes = {
 };
 
 FlairAvatar.contextTypes = {
-    matrixClient: React.PropTypes.instanceOf(MatrixClient).isRequired,
+    matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
 };
 
 export default class Flair extends React.Component {
@@ -134,5 +134,5 @@ Flair.propTypes = {
 // this.context.matrixClient everywhere instead of this.props.matrixClient.
 // See https://github.com/vector-im/riot-web/issues/4951.
 Flair.contextTypes = {
-    matrixClient: React.PropTypes.instanceOf(MatrixClient).isRequired,
+    matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
 };
diff --git a/src/components/views/elements/LanguageDropdown.js b/src/components/views/elements/LanguageDropdown.js
index 6c86296a38..365f9ded61 100644
--- a/src/components/views/elements/LanguageDropdown.js
+++ b/src/components/views/elements/LanguageDropdown.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import sdk from '../../../index';
 import * as languageHandler from '../../../languageHandler';
@@ -114,7 +115,7 @@ export default class LanguageDropdown extends React.Component {
 }
 
 LanguageDropdown.propTypes = {
-    className: React.PropTypes.string,
-    onOptionChange: React.PropTypes.func.isRequired,
-    value: React.PropTypes.string,
+    className: PropTypes.string,
+    onOptionChange: PropTypes.func.isRequired,
+    value: PropTypes.string,
 };
diff --git a/src/components/views/elements/MemberEventListSummary.js b/src/components/views/elements/MemberEventListSummary.js
index e2368a2fe3..3c58f90a2b 100644
--- a/src/components/views/elements/MemberEventListSummary.js
+++ b/src/components/views/elements/MemberEventListSummary.js
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 const MemberAvatar = require('../avatars/MemberAvatar.js');
 import { _t } from '../../../languageHandler';
@@ -23,19 +24,19 @@ module.exports = React.createClass({
 
     propTypes: {
         // An array of member events to summarise
-        events: React.PropTypes.array.isRequired,
+        events: PropTypes.array.isRequired,
         // An array of EventTiles to render when expanded
-        children: React.PropTypes.array.isRequired,
+        children: PropTypes.array.isRequired,
         // The maximum number of names to show in either each summary e.g. 2 would result "A, B and 234 others left"
-        summaryLength: React.PropTypes.number,
+        summaryLength: PropTypes.number,
         // The maximum number of avatars to display in the summary
-        avatarsMaxLength: React.PropTypes.number,
+        avatarsMaxLength: PropTypes.number,
         // The minimum number of events needed to trigger summarisation
-        threshold: React.PropTypes.number,
+        threshold: PropTypes.number,
         // Called when the MELS expansion is toggled
-        onToggle: React.PropTypes.func,
+        onToggle: PropTypes.func,
         // Whether or not to begin with state.expanded=true
-        startExpanded: React.PropTypes.bool,
+        startExpanded: PropTypes.bool,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/elements/PowerSelector.js b/src/components/views/elements/PowerSelector.js
index d5c167fac9..f8443c6ecd 100644
--- a/src/components/views/elements/PowerSelector.js
+++ b/src/components/views/elements/PowerSelector.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import * as Roles from '../../../Roles';
 import { _t } from '../../../languageHandler';
 
@@ -24,23 +25,23 @@ module.exports = React.createClass({
     displayName: 'PowerSelector',
 
     propTypes: {
-        value: React.PropTypes.number.isRequired,
+        value: PropTypes.number.isRequired,
         // The maximum value that can be set with the power selector
-        maxValue: React.PropTypes.number.isRequired,
+        maxValue: PropTypes.number.isRequired,
 
         // Default user power level for the room
-        usersDefault: React.PropTypes.number.isRequired,
+        usersDefault: PropTypes.number.isRequired,
 
         // if true, the <select/> should be a 'controlled' form element and updated by React
         // to reflect the current value, rather than left freeform.
         // MemberInfo uses controlled; RoomSettings uses non-controlled.
         //
         // ignored if disabled is truthy. false by default.
-        controlled: React.PropTypes.bool,
+        controlled: PropTypes.bool,
 
         // should the user be able to change the value? false by default.
-        disabled: React.PropTypes.bool,
-        onChange: React.PropTypes.func,
+        disabled: PropTypes.bool,
+        onChange: PropTypes.func,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/elements/ProgressBar.js b/src/components/views/elements/ProgressBar.js
index 861bfb1335..15da5d44f6 100644
--- a/src/components/views/elements/ProgressBar.js
+++ b/src/components/views/elements/ProgressBar.js
@@ -17,12 +17,13 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 
 module.exports = React.createClass({
     displayName: 'ProgressBar',
     propTypes: {
-        value: React.PropTypes.number,
-        max: React.PropTypes.number,
+        value: PropTypes.number,
+        max: PropTypes.number,
     },
 
     render: function() {
diff --git a/src/components/views/elements/SettingsFlag.js b/src/components/views/elements/SettingsFlag.js
index 782dc30ede..7f6c74538a 100644
--- a/src/components/views/elements/SettingsFlag.js
+++ b/src/components/views/elements/SettingsFlag.js
@@ -15,23 +15,24 @@ limitations under the License.
 */
 
 import React from "react";
+import PropTypes from 'prop-types';
 import SettingsStore from "../../../settings/SettingsStore";
 import { _t } from '../../../languageHandler';
 
 module.exports = React.createClass({
     displayName: 'SettingsFlag',
     propTypes: {
-        name: React.PropTypes.string.isRequired,
-        level: React.PropTypes.string.isRequired,
-        roomId: React.PropTypes.string, // for per-room settings
-        label: React.PropTypes.string, // untranslated
-        onChange: React.PropTypes.func,
-        isExplicit: React.PropTypes.bool,
-        manualSave: React.PropTypes.bool,
+        name: PropTypes.string.isRequired,
+        level: PropTypes.string.isRequired,
+        roomId: PropTypes.string, // for per-room settings
+        label: PropTypes.string, // untranslated
+        onChange: PropTypes.func,
+        isExplicit: PropTypes.bool,
+        manualSave: PropTypes.bool,
 
         // If group is supplied, then this will create a radio button instead.
-        group: React.PropTypes.string,
-        value: React.PropTypes.any, // the value for the radio button
+        group: PropTypes.string,
+        value: PropTypes.any, // the value for the radio button
     },
 
     getInitialState: function() {
diff --git a/src/components/views/elements/TagTile.js b/src/components/views/elements/TagTile.js
index a98cca9609..f52f758cc0 100644
--- a/src/components/views/elements/TagTile.js
+++ b/src/components/views/elements/TagTile.js
@@ -39,7 +39,7 @@ export default React.createClass({
     },
 
     contextTypes: {
-        matrixClient: React.PropTypes.instanceOf(MatrixClient).isRequired,
+        matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
     },
 
     getInitialState() {
diff --git a/src/components/views/elements/TintableSvg.js b/src/components/views/elements/TintableSvg.js
index 3649cbccdb..e04bf87793 100644
--- a/src/components/views/elements/TintableSvg.js
+++ b/src/components/views/elements/TintableSvg.js
@@ -18,16 +18,17 @@ limitations under the License.
 
 const React = require('react');
 const ReactDOM = require("react-dom");
+import PropTypes from 'prop-types';
 const Tinter = require("../../../Tinter");
 
 var TintableSvg = React.createClass({
     displayName: 'TintableSvg',
 
     propTypes: {
-        src: React.PropTypes.string.isRequired,
-        width: React.PropTypes.string.isRequired,
-        height: React.PropTypes.string.isRequired,
-        className: React.PropTypes.string,
+        src: PropTypes.string.isRequired,
+        width: PropTypes.string.isRequired,
+        height: PropTypes.string.isRequired,
+        className: PropTypes.string,
     },
 
     statics: {
diff --git a/src/components/views/elements/UserSelector.js b/src/components/views/elements/UserSelector.js
index a523c57d9f..a05f615e34 100644
--- a/src/components/views/elements/UserSelector.js
+++ b/src/components/views/elements/UserSelector.js
@@ -17,14 +17,15 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
 module.exports = React.createClass({
     displayName: 'UserSelector',
 
     propTypes: {
-        onChange: React.PropTypes.func,
-        selected_users: React.PropTypes.arrayOf(React.PropTypes.string),
+        onChange: PropTypes.func,
+        selected_users: PropTypes.arrayOf(React.PropTypes.string),
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/groups/GroupRoomTile.js b/src/components/views/groups/GroupRoomTile.js
index 907ce93a4a..a4961fefa9 100644
--- a/src/components/views/groups/GroupRoomTile.js
+++ b/src/components/views/groups/GroupRoomTile.js
@@ -66,7 +66,7 @@ const GroupRoomTile = React.createClass({
 });
 
 GroupRoomTile.contextTypes = {
-    matrixClient: React.PropTypes.instanceOf(MatrixClient).isRequired,
+    matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
 };
 
 
diff --git a/src/components/views/groups/GroupTile.js b/src/components/views/groups/GroupTile.js
index 7ea67de98e..ce426a9b78 100644
--- a/src/components/views/groups/GroupTile.js
+++ b/src/components/views/groups/GroupTile.js
@@ -33,7 +33,7 @@ const GroupTile = React.createClass({
     },
 
     contextTypes: {
-        matrixClient: React.PropTypes.instanceOf(MatrixClient).isRequired,
+        matrixClient: PropTypes.instanceOf(MatrixClient).isRequired,
     },
 
     getInitialState() {
diff --git a/src/components/views/login/CaptchaForm.js b/src/components/views/login/CaptchaForm.js
index 21e5094b28..ab1bfbd393 100644
--- a/src/components/views/login/CaptchaForm.js
+++ b/src/components/views/login/CaptchaForm.js
@@ -18,6 +18,7 @@ limitations under the License.
 
 import React from 'react';
 import ReactDOM from 'react-dom';
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
 const DIV_ID = 'mx_recaptcha';
@@ -29,10 +30,10 @@ module.exports = React.createClass({
     displayName: 'CaptchaForm',
 
     propTypes: {
-        sitePublicKey: React.PropTypes.string,
+        sitePublicKey: PropTypes.string,
 
         // called with the captcha response
-        onCaptchaResponse: React.PropTypes.func,
+        onCaptchaResponse: PropTypes.func,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/login/CasLogin.js b/src/components/views/login/CasLogin.js
index 49d121687d..9219c79733 100644
--- a/src/components/views/login/CasLogin.js
+++ b/src/components/views/login/CasLogin.js
@@ -17,13 +17,14 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
 module.exports = React.createClass({
     displayName: 'CasLogin',
 
     propTypes: {
-      onSubmit: React.PropTypes.func, // fn()
+      onSubmit: PropTypes.func, // fn()
     },
 
     render: function() {
diff --git a/src/components/views/login/CountryDropdown.js b/src/components/views/login/CountryDropdown.js
index d8695bb1c1..3fd28e32d2 100644
--- a/src/components/views/login/CountryDropdown.js
+++ b/src/components/views/login/CountryDropdown.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import sdk from '../../../index';
 
@@ -131,11 +132,11 @@ export default class CountryDropdown extends React.Component {
 }
 
 CountryDropdown.propTypes = {
-    className: React.PropTypes.string,
-    isSmall: React.PropTypes.bool,
+    className: PropTypes.string,
+    isSmall: PropTypes.bool,
     // if isSmall, show +44 in the selected value
-    showPrefix: React.PropTypes.bool,
-    onOptionChange: React.PropTypes.func.isRequired,
-    value: React.PropTypes.string,
-    disabled: React.PropTypes.bool,
+    showPrefix: PropTypes.bool,
+    onOptionChange: PropTypes.func.isRequired,
+    value: PropTypes.string,
+    disabled: PropTypes.bool,
 };
diff --git a/src/components/views/login/InteractiveAuthEntryComponents.js b/src/components/views/login/InteractiveAuthEntryComponents.js
index e8997b4112..eeda5cd9f3 100644
--- a/src/components/views/login/InteractiveAuthEntryComponents.js
+++ b/src/components/views/login/InteractiveAuthEntryComponents.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import url from 'url';
 import classnames from 'classnames';
 
@@ -69,12 +70,12 @@ export const PasswordAuthEntry = React.createClass({
     },
 
     propTypes: {
-        matrixClient: React.PropTypes.object.isRequired,
-        submitAuthDict: React.PropTypes.func.isRequired,
-        errorText: React.PropTypes.string,
+        matrixClient: PropTypes.object.isRequired,
+        submitAuthDict: PropTypes.func.isRequired,
+        errorText: PropTypes.string,
         // is the auth logic currently waiting for something to
         // happen?
-        busy: React.PropTypes.bool,
+        busy: PropTypes.bool,
     },
 
     getInitialState: function() {
@@ -158,10 +159,10 @@ export const RecaptchaAuthEntry = React.createClass({
     },
 
     propTypes: {
-        submitAuthDict: React.PropTypes.func.isRequired,
-        stageParams: React.PropTypes.object.isRequired,
-        errorText: React.PropTypes.string,
-        busy: React.PropTypes.bool,
+        submitAuthDict: PropTypes.func.isRequired,
+        stageParams: PropTypes.object.isRequired,
+        errorText: PropTypes.string,
+        busy: PropTypes.bool,
     },
 
     _onCaptchaResponse: function(response) {
@@ -200,15 +201,15 @@ export const EmailIdentityAuthEntry = React.createClass({
     },
 
     propTypes: {
-        matrixClient: React.PropTypes.object.isRequired,
-        submitAuthDict: React.PropTypes.func.isRequired,
-        authSessionId: React.PropTypes.string.isRequired,
-        clientSecret: React.PropTypes.string.isRequired,
-        inputs: React.PropTypes.object.isRequired,
-        stageState: React.PropTypes.object.isRequired,
-        fail: React.PropTypes.func.isRequired,
-        setEmailSid: React.PropTypes.func.isRequired,
-        makeRegistrationUrl: React.PropTypes.func.isRequired,
+        matrixClient: PropTypes.object.isRequired,
+        submitAuthDict: PropTypes.func.isRequired,
+        authSessionId: PropTypes.string.isRequired,
+        clientSecret: PropTypes.string.isRequired,
+        inputs: PropTypes.object.isRequired,
+        stageState: PropTypes.object.isRequired,
+        fail: PropTypes.func.isRequired,
+        setEmailSid: PropTypes.func.isRequired,
+        makeRegistrationUrl: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
@@ -275,15 +276,15 @@ export const MsisdnAuthEntry = React.createClass({
     },
 
     propTypes: {
-        inputs: React.PropTypes.shape({
-            phoneCountry: React.PropTypes.string,
-            phoneNumber: React.PropTypes.string,
+        inputs: PropTypes.shape({
+            phoneCountry: PropTypes.string,
+            phoneNumber: PropTypes.string,
         }),
-        fail: React.PropTypes.func,
-        clientSecret: React.PropTypes.func,
-        submitAuthDict: React.PropTypes.func.isRequired,
-        matrixClient: React.PropTypes.object,
-        submitAuthDict: React.PropTypes.func,
+        fail: PropTypes.func,
+        clientSecret: PropTypes.func,
+        submitAuthDict: PropTypes.func.isRequired,
+        matrixClient: PropTypes.object,
+        submitAuthDict: PropTypes.func,
     },
 
     getInitialState: function() {
@@ -405,11 +406,11 @@ export const FallbackAuthEntry = React.createClass({
     displayName: 'FallbackAuthEntry',
 
     propTypes: {
-        matrixClient: React.PropTypes.object.isRequired,
-        authSessionId: React.PropTypes.string.isRequired,
-        loginType: React.PropTypes.string.isRequired,
-        submitAuthDict: React.PropTypes.func.isRequired,
-        errorText: React.PropTypes.string,
+        matrixClient: PropTypes.object.isRequired,
+        authSessionId: PropTypes.string.isRequired,
+        loginType: PropTypes.string.isRequired,
+        submitAuthDict: PropTypes.func.isRequired,
+        errorText: PropTypes.string,
     },
 
     componentWillMount: function() {
diff --git a/src/components/views/login/PasswordLogin.js b/src/components/views/login/PasswordLogin.js
index 83bb41c1a3..71dfbe2c36 100644
--- a/src/components/views/login/PasswordLogin.js
+++ b/src/components/views/login/PasswordLogin.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
@@ -256,17 +257,17 @@ PasswordLogin.LOGIN_FIELD_MXID = "login_field_mxid";
 PasswordLogin.LOGIN_FIELD_PHONE = "login_field_phone";
 
 PasswordLogin.propTypes = {
-    onSubmit: React.PropTypes.func.isRequired, // fn(username, password)
-    onForgotPasswordClick: React.PropTypes.func, // fn()
-    initialUsername: React.PropTypes.string,
-    initialPhoneCountry: React.PropTypes.string,
-    initialPhoneNumber: React.PropTypes.string,
-    initialPassword: React.PropTypes.string,
-    onUsernameChanged: React.PropTypes.func,
-    onPhoneCountryChanged: React.PropTypes.func,
-    onPhoneNumberChanged: React.PropTypes.func,
-    onPasswordChanged: React.PropTypes.func,
-    loginIncorrect: React.PropTypes.bool,
+    onSubmit: PropTypes.func.isRequired, // fn(username, password)
+    onForgotPasswordClick: PropTypes.func, // fn()
+    initialUsername: PropTypes.string,
+    initialPhoneCountry: PropTypes.string,
+    initialPhoneNumber: PropTypes.string,
+    initialPassword: PropTypes.string,
+    onUsernameChanged: PropTypes.func,
+    onPhoneCountryChanged: PropTypes.func,
+    onPhoneNumberChanged: PropTypes.func,
+    onPasswordChanged: PropTypes.func,
+    loginIncorrect: PropTypes.bool,
 };
 
 module.exports = PasswordLogin;
diff --git a/src/components/views/login/RegistrationForm.js b/src/components/views/login/RegistrationForm.js
index 32a36c3897..fff808cf22 100644
--- a/src/components/views/login/RegistrationForm.js
+++ b/src/components/views/login/RegistrationForm.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import { field_input_incorrect } from '../../../UiEffects';
 import sdk from '../../../index';
 import Email from '../../../email';
@@ -40,25 +41,25 @@ module.exports = React.createClass({
 
     propTypes: {
         // Values pre-filled in the input boxes when the component loads
-        defaultEmail: React.PropTypes.string,
-        defaultPhoneCountry: React.PropTypes.string,
-        defaultPhoneNumber: React.PropTypes.string,
-        defaultUsername: React.PropTypes.string,
-        defaultPassword: React.PropTypes.string,
-        teamsConfig: React.PropTypes.shape({
+        defaultEmail: PropTypes.string,
+        defaultPhoneCountry: PropTypes.string,
+        defaultPhoneNumber: PropTypes.string,
+        defaultUsername: PropTypes.string,
+        defaultPassword: PropTypes.string,
+        teamsConfig: PropTypes.shape({
             // Email address to request new teams
-            supportEmail: React.PropTypes.string,
-            teams: React.PropTypes.arrayOf(React.PropTypes.shape({
+            supportEmail: PropTypes.string,
+            teams: PropTypes.arrayOf(React.PropTypes.shape({
                 // The displayed name of the team
-                "name": React.PropTypes.string,
+                "name": PropTypes.string,
                 // The domain of team email addresses
-                "domain": React.PropTypes.string,
+                "domain": PropTypes.string,
             })).required,
         }),
 
-        minPasswordLength: React.PropTypes.number,
-        onError: React.PropTypes.func,
-        onRegisterClick: React.PropTypes.func.isRequired, // onRegisterClick(Object) => ?Promise
+        minPasswordLength: PropTypes.number,
+        onError: PropTypes.func,
+        onRegisterClick: PropTypes.func.isRequired, // onRegisterClick(Object) => ?Promise
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/login/ServerConfig.js b/src/components/views/login/ServerConfig.js
index d53c7238b1..a6944ec20a 100644
--- a/src/components/views/login/ServerConfig.js
+++ b/src/components/views/login/ServerConfig.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const Modal = require('../../../Modal');
 const sdk = require('../../../index');
 import { _t } from '../../../languageHandler';
@@ -28,24 +29,24 @@ module.exports = React.createClass({
     displayName: 'ServerConfig',
 
     propTypes: {
-        onServerConfigChange: React.PropTypes.func,
+        onServerConfigChange: PropTypes.func,
 
         // default URLs are defined in config.json (or the hardcoded defaults)
         // they are used if the user has not overridden them with a custom URL.
         // In other words, if the custom URL is blank, the default is used.
-        defaultHsUrl: React.PropTypes.string, // e.g. https://matrix.org
-        defaultIsUrl: React.PropTypes.string, // e.g. https://vector.im
+        defaultHsUrl: PropTypes.string, // e.g. https://matrix.org
+        defaultIsUrl: PropTypes.string, // e.g. https://vector.im
 
         // custom URLs are explicitly provided by the user and override the
         // default URLs.  The user enters them via the component's input fields,
         // which is reflected on these properties whenever on..UrlChanged fires.
         // They are persisted in localStorage by MatrixClientPeg, and so can
         // override the default URLs when the component initially loads.
-        customHsUrl: React.PropTypes.string,
-        customIsUrl: React.PropTypes.string,
+        customHsUrl: PropTypes.string,
+        customIsUrl: PropTypes.string,
 
-        withToggleButton: React.PropTypes.bool,
-        delayTimeMs: React.PropTypes.number, // time to wait before invoking onChanged
+        withToggleButton: PropTypes.bool,
+        delayTimeMs: PropTypes.number, // time to wait before invoking onChanged
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js
index 8eedf4e1fe..d106d7368e 100644
--- a/src/components/views/messages/MFileBody.js
+++ b/src/components/views/messages/MFileBody.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import filesize from 'filesize';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import sdk from '../../../index';
@@ -191,7 +192,7 @@ module.exports = React.createClass({
     },
 
     contextTypes: {
-        appConfig: React.PropTypes.object,
+        appConfig: PropTypes.object,
     },
 
     /**
diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js
index ba7f8000ea..608f48112e 100644
--- a/src/components/views/messages/MImageBody.js
+++ b/src/components/views/messages/MImageBody.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import MFileBody from './MFileBody';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import ImageUtils from '../../../ImageUtils';
@@ -33,10 +34,10 @@ module.exports = React.createClass({
 
     propTypes: {
         /* the MatrixEvent to show */
-        mxEvent: React.PropTypes.object.isRequired,
+        mxEvent: PropTypes.object.isRequired,
 
         /* called when the image has loaded */
-        onWidgetLoad: React.PropTypes.func.isRequired,
+        onWidgetLoad: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/messages/MVideoBody.js b/src/components/views/messages/MVideoBody.js
index 2e8f0071ac..21edbae9a2 100644
--- a/src/components/views/messages/MVideoBody.js
+++ b/src/components/views/messages/MVideoBody.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import MFileBody from './MFileBody';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { decryptFile, readBlobAsDataUri } from '../../../utils/DecryptFile';
@@ -29,10 +30,10 @@ module.exports = React.createClass({
 
     propTypes: {
         /* the MatrixEvent to show */
-        mxEvent: React.PropTypes.object.isRequired,
+        mxEvent: PropTypes.object.isRequired,
 
         /* called when the video has loaded */
-        onWidgetLoad: React.PropTypes.func.isRequired,
+        onWidgetLoad: PropTypes.func.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js
index deda1d8d20..d35959599c 100644
--- a/src/components/views/messages/MessageEvent.js
+++ b/src/components/views/messages/MessageEvent.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const sdk = require('../../../index');
 
 module.exports = React.createClass({
@@ -24,22 +25,22 @@ module.exports = React.createClass({
 
     propTypes: {
         /* the MatrixEvent to show */
-        mxEvent: React.PropTypes.object.isRequired,
+        mxEvent: PropTypes.object.isRequired,
 
         /* a list of words to highlight */
-        highlights: React.PropTypes.array,
+        highlights: PropTypes.array,
 
         /* link URL for the highlights */
-        highlightLink: React.PropTypes.string,
+        highlightLink: PropTypes.string,
 
         /* should show URL previews for this event */
-        showUrlPreview: React.PropTypes.bool,
+        showUrlPreview: PropTypes.bool,
 
         /* callback called when dynamic content in events are loaded */
-        onWidgetLoad: React.PropTypes.func,
+        onWidgetLoad: PropTypes.func,
 
         /* the shsape of the tile, used */
-        tileShape: React.PropTypes.string,
+        tileShape: PropTypes.string,
     },
 
     getEventTileOps: function() {
diff --git a/src/components/views/messages/RoomAvatarEvent.js b/src/components/views/messages/RoomAvatarEvent.js
index 3a572d0cbe..d035fc9237 100644
--- a/src/components/views/messages/RoomAvatarEvent.js
+++ b/src/components/views/messages/RoomAvatarEvent.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import { ContentRepo } from 'matrix-js-sdk';
 import { _t } from '../../../languageHandler';
@@ -27,7 +28,7 @@ module.exports = React.createClass({
 
     propTypes: {
         /* the MatrixEvent to show */
-        mxEvent: React.PropTypes.object.isRequired,
+        mxEvent: PropTypes.object.isRequired,
     },
 
     onAvatarClick: function(name) {
diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js
index 4b096d0a76..6a970a0563 100644
--- a/src/components/views/messages/TextualBody.js
+++ b/src/components/views/messages/TextualBody.js
@@ -18,6 +18,7 @@ limitations under the License.
 
 import React from 'react';
 import ReactDOM from 'react-dom';
+import PropTypes from 'prop-types';
 import highlight from 'highlight.js';
 import * as HtmlUtils from '../../../HtmlUtils';
 import * as linkify from 'linkifyjs';
@@ -43,19 +44,19 @@ module.exports = React.createClass({
 
     propTypes: {
         /* the MatrixEvent to show */
-        mxEvent: React.PropTypes.object.isRequired,
+        mxEvent: PropTypes.object.isRequired,
 
         /* a list of words to highlight */
-        highlights: React.PropTypes.array,
+        highlights: PropTypes.array,
 
         /* link URL for the highlights */
-        highlightLink: React.PropTypes.string,
+        highlightLink: PropTypes.string,
 
         /* should show URL previews for this event */
-        showUrlPreview: React.PropTypes.bool,
+        showUrlPreview: PropTypes.bool,
 
         /* callback for when our widget has loaded */
-        onWidgetLoad: React.PropTypes.func,
+        onWidgetLoad: PropTypes.func,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/messages/TextualEvent.js b/src/components/views/messages/TextualEvent.js
index be0962a868..6c87000615 100644
--- a/src/components/views/messages/TextualEvent.js
+++ b/src/components/views/messages/TextualEvent.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 
 const TextForEvent = require('../../../TextForEvent');
 import sdk from '../../../index';
@@ -26,7 +27,7 @@ module.exports = React.createClass({
 
     propTypes: {
         /* the MatrixEvent to show */
-        mxEvent: React.PropTypes.object.isRequired,
+        mxEvent: PropTypes.object.isRequired,
     },
 
     render: function() {
diff --git a/src/components/views/room_settings/AliasSettings.js b/src/components/views/room_settings/AliasSettings.js
index f1c5c0000c..2915a061de 100644
--- a/src/components/views/room_settings/AliasSettings.js
+++ b/src/components/views/room_settings/AliasSettings.js
@@ -16,6 +16,7 @@ limitations under the License.
 
 import Promise from 'bluebird';
 const React = require('react');
+import PropTypes from 'prop-types';
 const ObjectUtils = require("../../../ObjectUtils");
 const MatrixClientPeg = require('../../../MatrixClientPeg');
 const sdk = require("../../../index");
@@ -26,11 +27,11 @@ module.exports = React.createClass({
     displayName: 'AliasSettings',
 
     propTypes: {
-        roomId: React.PropTypes.string.isRequired,
-        canSetCanonicalAlias: React.PropTypes.bool.isRequired,
-        canSetAliases: React.PropTypes.bool.isRequired,
-        aliasEvents: React.PropTypes.array, // [MatrixEvent]
-        canonicalAliasEvent: React.PropTypes.object, // MatrixEvent
+        roomId: PropTypes.string.isRequired,
+        canSetCanonicalAlias: PropTypes.bool.isRequired,
+        canSetAliases: PropTypes.bool.isRequired,
+        aliasEvents: PropTypes.array, // [MatrixEvent]
+        canonicalAliasEvent: PropTypes.object, // MatrixEvent
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/room_settings/ColorSettings.js b/src/components/views/room_settings/ColorSettings.js
index b6b8c9bad3..e82d3ffb0a 100644
--- a/src/components/views/room_settings/ColorSettings.js
+++ b/src/components/views/room_settings/ColorSettings.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 import Promise from 'bluebird';
 const React = require('react');
+import PropTypes from 'prop-types';
 
 const sdk = require('../../../index');
 const Tinter = require('../../../Tinter');
@@ -42,7 +43,7 @@ module.exports = React.createClass({
     displayName: 'ColorSettings',
 
     propTypes: {
-        room: React.PropTypes.object.isRequired,
+        room: PropTypes.object.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/room_settings/RelatedGroupSettings.js b/src/components/views/room_settings/RelatedGroupSettings.js
index e1fc7cd80d..4f02dc6c20 100644
--- a/src/components/views/room_settings/RelatedGroupSettings.js
+++ b/src/components/views/room_settings/RelatedGroupSettings.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import {MatrixEvent, MatrixClient} from 'matrix-js-sdk';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
@@ -27,13 +28,13 @@ module.exports = React.createClass({
     displayName: 'RelatedGroupSettings',
 
     propTypes: {
-        roomId: React.PropTypes.string.isRequired,
-        canSetRelatedGroups: React.PropTypes.bool.isRequired,
-        relatedGroupsEvent: React.PropTypes.instanceOf(MatrixEvent),
+        roomId: PropTypes.string.isRequired,
+        canSetRelatedGroups: PropTypes.bool.isRequired,
+        relatedGroupsEvent: PropTypes.instanceOf(MatrixEvent),
     },
 
     contextTypes: {
-        matrixClient: React.PropTypes.instanceOf(MatrixClient),
+        matrixClient: PropTypes.instanceOf(MatrixClient),
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/room_settings/UrlPreviewSettings.js b/src/components/views/room_settings/UrlPreviewSettings.js
index e4a8c9d353..ed58d610aa 100644
--- a/src/components/views/room_settings/UrlPreviewSettings.js
+++ b/src/components/views/room_settings/UrlPreviewSettings.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const sdk = require("../../../index");
 import { _t, _td } from '../../../languageHandler';
 import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
@@ -25,7 +26,7 @@ module.exports = React.createClass({
     displayName: 'UrlPreviewSettings',
 
     propTypes: {
-        room: React.PropTypes.object,
+        room: PropTypes.object,
     },
 
     saveSettings: function() {
diff --git a/src/components/views/rooms/AppsDrawer.js b/src/components/views/rooms/AppsDrawer.js
index e29f46fd37..9707cd95de 100644
--- a/src/components/views/rooms/AppsDrawer.js
+++ b/src/components/views/rooms/AppsDrawer.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import AppTile from '../elements/AppTile';
 import Modal from '../../../Modal';
@@ -36,7 +37,7 @@ module.exports = React.createClass({
     displayName: 'AppsDrawer',
 
     propTypes: {
-        room: React.PropTypes.object.isRequired,
+        room: PropTypes.object.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/rooms/AuxPanel.js b/src/components/views/rooms/AuxPanel.js
index c0857d9691..2713b1d30f 100644
--- a/src/components/views/rooms/AuxPanel.js
+++ b/src/components/views/rooms/AuxPanel.js
@@ -16,6 +16,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import sdk from '../../../index';
 import dis from "../../../dispatcher";
@@ -29,26 +30,26 @@ module.exports = React.createClass({
 
     propTypes: {
         // js-sdk room object
-        room: React.PropTypes.object.isRequired,
-        userId: React.PropTypes.string.isRequired,
-        showApps: React.PropTypes.bool,
+        room: PropTypes.object.isRequired,
+        userId: PropTypes.string.isRequired,
+        showApps: PropTypes.bool,
 
         // Conference Handler implementation
-        conferenceHandler: React.PropTypes.object,
+        conferenceHandler: PropTypes.object,
 
         // set to true to show the file drop target
-        draggingFile: React.PropTypes.bool,
+        draggingFile: PropTypes.bool,
 
         // set to true to show the 'active conf call' banner
-        displayConfCallNotification: React.PropTypes.bool,
+        displayConfCallNotification: PropTypes.bool,
 
         // maxHeight attribute for the aux panel and the video
         // therein
-        maxHeight: React.PropTypes.number,
+        maxHeight: PropTypes.number,
 
         // a callback which is called when the content of the aux panel changes
         // content in a way that is likely to make it change size.
-        onResize: React.PropTypes.func,
+        onResize: PropTypes.func,
     },
 
     shouldComponentUpdate: function(nextProps, nextState) {
diff --git a/src/components/views/rooms/EntityTile.js b/src/components/views/rooms/EntityTile.js
index ffcb289437..949eebada0 100644
--- a/src/components/views/rooms/EntityTile.js
+++ b/src/components/views/rooms/EntityTile.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 
 const MatrixClientPeg = require('../../../MatrixClientPeg');
 const sdk = require('../../../index');
@@ -51,18 +52,18 @@ const EntityTile = React.createClass({
     displayName: 'EntityTile',
 
     propTypes: {
-        name: React.PropTypes.string,
-        title: React.PropTypes.string,
-        avatarJsx: React.PropTypes.any, // <BaseAvatar />
-        className: React.PropTypes.string,
-        presenceState: React.PropTypes.string,
-        presenceLastActiveAgo: React.PropTypes.number,
-        presenceLastTs: React.PropTypes.number,
-        presenceCurrentlyActive: React.PropTypes.bool,
-        showInviteButton: React.PropTypes.bool,
-        shouldComponentUpdate: React.PropTypes.func,
-        onClick: React.PropTypes.func,
-        suppressOnHover: React.PropTypes.bool,
+        name: PropTypes.string,
+        title: PropTypes.string,
+        avatarJsx: PropTypes.any, // <BaseAvatar />
+        className: PropTypes.string,
+        presenceState: PropTypes.string,
+        presenceLastActiveAgo: PropTypes.number,
+        presenceLastTs: PropTypes.number,
+        presenceCurrentlyActive: PropTypes.bool,
+        showInviteButton: PropTypes.bool,
+        shouldComponentUpdate: PropTypes.func,
+        onClick: PropTypes.func,
+        suppressOnHover: PropTypes.bool,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index 0b55c3aa2a..d5589000c6 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -18,6 +18,7 @@ limitations under the License.
 
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const classNames = require("classnames");
 import { _t, _td } from '../../../languageHandler';
 const Modal = require('../../../Modal');
@@ -75,65 +76,65 @@ module.exports = withMatrixClient(React.createClass({
 
     propTypes: {
         /* MatrixClient instance for sender verification etc */
-        matrixClient: React.PropTypes.object.isRequired,
+        matrixClient: PropTypes.object.isRequired,
 
         /* the MatrixEvent to show */
-        mxEvent: React.PropTypes.object.isRequired,
+        mxEvent: PropTypes.object.isRequired,
 
         /* true if mxEvent is redacted. This is a prop because using mxEvent.isRedacted()
          * might not be enough when deciding shouldComponentUpdate - prevProps.mxEvent
          * references the same this.props.mxEvent.
          */
-        isRedacted: React.PropTypes.bool,
+        isRedacted: PropTypes.bool,
 
         /* true if this is a continuation of the previous event (which has the
          * effect of not showing another avatar/displayname
          */
-        continuation: React.PropTypes.bool,
+        continuation: PropTypes.bool,
 
         /* true if this is the last event in the timeline (which has the effect
          * of always showing the timestamp)
          */
-        last: React.PropTypes.bool,
+        last: PropTypes.bool,
 
         /* true if this is search context (which has the effect of greying out
          * the text
          */
-        contextual: React.PropTypes.bool,
+        contextual: PropTypes.bool,
 
         /* a list of words to highlight, ordered by longest first */
-        highlights: React.PropTypes.array,
+        highlights: PropTypes.array,
 
         /* link URL for the highlights */
-        highlightLink: React.PropTypes.string,
+        highlightLink: PropTypes.string,
 
         /* should show URL previews for this event */
-        showUrlPreview: React.PropTypes.bool,
+        showUrlPreview: PropTypes.bool,
 
         /* is this the focused event */
-        isSelectedEvent: React.PropTypes.bool,
+        isSelectedEvent: PropTypes.bool,
 
         /* callback called when dynamic content in events are loaded */
-        onWidgetLoad: React.PropTypes.func,
+        onWidgetLoad: PropTypes.func,
 
         /* a list of read-receipts we should show. Each object has a 'roomMember' and 'ts'. */
-        readReceipts: React.PropTypes.arrayOf(React.PropTypes.object),
+        readReceipts: PropTypes.arrayOf(React.PropTypes.object),
 
         /* opaque readreceipt info for each userId; used by ReadReceiptMarker
          * to manage its animations. Should be an empty object when the room
          * first loads
          */
-        readReceiptMap: React.PropTypes.object,
+        readReceiptMap: PropTypes.object,
 
         /* A function which is used to check if the parent panel is being
          * unmounted, to avoid unnecessary work. Should return true if we
          * are being unmounted.
          */
-        checkUnmounting: React.PropTypes.func,
+        checkUnmounting: PropTypes.func,
 
         /* the status of this event - ie, mxEvent.status. Denormalised to here so
          * that we can tell when it changes. */
-        eventSendStatus: React.PropTypes.string,
+        eventSendStatus: PropTypes.string,
 
         /* the shape of the tile. by default, the layout is intended for the
          * normal room timeline.  alternative values are: "file_list", "file_grid"
@@ -142,10 +143,10 @@ module.exports = withMatrixClient(React.createClass({
          * boiilerplatey.  So just make the necessary render decisions conditional
          * for now.
          */
-        tileShape: React.PropTypes.string,
+        tileShape: PropTypes.string,
 
         // show twelve hour timestamps
-        isTwelveHour: React.PropTypes.bool,
+        isTwelveHour: PropTypes.bool,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/rooms/ForwardMessage.js b/src/components/views/rooms/ForwardMessage.js
index 6f9d1d0b69..11ca7487cc 100644
--- a/src/components/views/rooms/ForwardMessage.js
+++ b/src/components/views/rooms/ForwardMessage.js
@@ -16,6 +16,7 @@
  */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 import dis from '../../../dispatcher';
 import { KeyCode } from '../../../Keyboard';
@@ -25,7 +26,7 @@ module.exports = React.createClass({
     displayName: 'ForwardMessage',
 
     propTypes: {
-        onCancelClick: React.PropTypes.func.isRequired,
+        onCancelClick: PropTypes.func.isRequired,
     },
 
     componentWillMount: function() {
diff --git a/src/components/views/rooms/LinkPreviewWidget.js b/src/components/views/rooms/LinkPreviewWidget.js
index d69a8fbcf1..2c70f36e07 100644
--- a/src/components/views/rooms/LinkPreviewWidget.js
+++ b/src/components/views/rooms/LinkPreviewWidget.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 
 const sdk = require('../../../index');
 const MatrixClientPeg = require('../../../MatrixClientPeg');
@@ -32,10 +33,10 @@ module.exports = React.createClass({
     displayName: 'LinkPreviewWidget',
 
     propTypes: {
-        link: React.PropTypes.string.isRequired, // the URL being previewed
-        mxEvent: React.PropTypes.object.isRequired, // the Event associated with the preview
-        onCancelClick: React.PropTypes.func, // called when the preview's cancel ('hide') button is clicked
-        onWidgetLoad: React.PropTypes.func, // called when the preview's contents has loaded
+        link: PropTypes.string.isRequired, // the URL being previewed
+        mxEvent: PropTypes.object.isRequired, // the Event associated with the preview
+        onCancelClick: PropTypes.func, // called when the preview's cancel ('hide') button is clicked
+        onWidgetLoad: PropTypes.func, // called when the preview's contents has loaded
     },
 
     getInitialState: function() {
diff --git a/src/components/views/rooms/MemberDeviceInfo.js b/src/components/views/rooms/MemberDeviceInfo.js
index 6e284fc886..41ed995ffb 100644
--- a/src/components/views/rooms/MemberDeviceInfo.js
+++ b/src/components/views/rooms/MemberDeviceInfo.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
 
@@ -65,6 +66,6 @@ export default class MemberDeviceInfo extends React.Component {
 
 MemberDeviceInfo.displayName = 'MemberDeviceInfo';
 MemberDeviceInfo.propTypes = {
-    userId: React.PropTypes.string.isRequired,
-    device: React.PropTypes.object.isRequired,
+    userId: PropTypes.string.isRequired,
+    device: PropTypes.object.isRequired,
 };
diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js
index 119355bc82..a711314709 100644
--- a/src/components/views/rooms/MemberInfo.js
+++ b/src/components/views/rooms/MemberInfo.js
@@ -27,6 +27,7 @@ limitations under the License.
  * 'isTargetMod': boolean
  */
 import React from 'react';
+import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import dis from '../../../dispatcher';
 import Modal from '../../../Modal';
@@ -45,8 +46,8 @@ module.exports = withMatrixClient(React.createClass({
     displayName: 'MemberInfo',
 
     propTypes: {
-        matrixClient: React.PropTypes.object.isRequired,
-        member: React.PropTypes.object.isRequired,
+        matrixClient: PropTypes.object.isRequired,
+        member: PropTypes.object.isRequired,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/rooms/MemberTile.js b/src/components/views/rooms/MemberTile.js
index 4848c4b258..50ee6befa8 100644
--- a/src/components/views/rooms/MemberTile.js
+++ b/src/components/views/rooms/MemberTile.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 
 const MatrixClientPeg = require('../../../MatrixClientPeg');
 const sdk = require('../../../index');
@@ -28,7 +29,7 @@ module.exports = React.createClass({
     displayName: 'MemberTile',
 
     propTypes: {
-        member: React.PropTypes.any.isRequired, // RoomMember
+        member: PropTypes.any.isRequired, // RoomMember
     },
 
     getInitialState: function() {
diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js
index 2841f30423..f3492de25b 100644
--- a/src/components/views/rooms/MessageComposer.js
+++ b/src/components/views/rooms/MessageComposer.js
@@ -15,6 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 import CallHandler from '../../../CallHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
@@ -399,17 +400,17 @@ export default class MessageComposer extends React.Component {
 MessageComposer.propTypes = {
     // a callback which is called when the height of the composer is
     // changed due to a change in content.
-    onResize: React.PropTypes.func,
+    onResize: PropTypes.func,
 
     // js-sdk Room object
-    room: React.PropTypes.object.isRequired,
+    room: PropTypes.object.isRequired,
 
     // string representing the current voip call state
-    callState: React.PropTypes.string,
+    callState: PropTypes.string,
 
     // callback when a file to upload is chosen
-    uploadFile: React.PropTypes.func.isRequired,
+    uploadFile: PropTypes.func.isRequired,
 
     // string representing the current room app drawer state
-    showApps: React.PropTypes.bool,
+    showApps: PropTypes.bool,
 };
diff --git a/src/components/views/rooms/MessageComposerInput.js b/src/components/views/rooms/MessageComposerInput.js
index 005a63607d..699d875f2f 100644
--- a/src/components/views/rooms/MessageComposerInput.js
+++ b/src/components/views/rooms/MessageComposerInput.js
@@ -15,6 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 import React from 'react';
+import PropTypes from 'prop-types';
 import type SyntheticKeyboardEvent from 'react/lib/SyntheticKeyboardEvent';
 
 import {Editor, EditorState, RichUtils, CompositeDecorator, Modifier,
@@ -86,15 +87,15 @@ export default class MessageComposerInput extends React.Component {
     static propTypes = {
         // a callback which is called when the height of the composer is
         // changed due to a change in content.
-        onResize: React.PropTypes.func,
+        onResize: PropTypes.func,
 
         // js-sdk Room object
-        room: React.PropTypes.object.isRequired,
+        room: PropTypes.object.isRequired,
 
         // called with current plaintext content (as a string) whenever it changes
-        onContentChanged: React.PropTypes.func,
+        onContentChanged: PropTypes.func,
 
-        onInputStateChanged: React.PropTypes.func,
+        onInputStateChanged: PropTypes.func,
     };
 
     static getKeyBinding(ev: SyntheticKeyboardEvent): string {
@@ -1178,15 +1179,15 @@ export default class MessageComposerInput extends React.Component {
 MessageComposerInput.propTypes = {
     // a callback which is called when the height of the composer is
     // changed due to a change in content.
-    onResize: React.PropTypes.func,
+    onResize: PropTypes.func,
 
     // js-sdk Room object
-    room: React.PropTypes.object.isRequired,
+    room: PropTypes.object.isRequired,
 
     // called with current plaintext content (as a string) whenever it changes
-    onContentChanged: React.PropTypes.func,
+    onContentChanged: PropTypes.func,
 
-    onFilesPasted: React.PropTypes.func,
+    onFilesPasted: PropTypes.func,
 
-    onInputStateChanged: React.PropTypes.func,
+    onInputStateChanged: PropTypes.func,
 };
diff --git a/src/components/views/rooms/PinnedEventTile.js b/src/components/views/rooms/PinnedEventTile.js
index 65b41d946a..b63fdde0a8 100644
--- a/src/components/views/rooms/PinnedEventTile.js
+++ b/src/components/views/rooms/PinnedEventTile.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from "react";
+import PropTypes from 'prop-types';
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import dis from "../../../dispatcher";
 import AccessibleButton from "../elements/AccessibleButton";
@@ -25,9 +26,9 @@ import { _t } from '../../../languageHandler';
 module.exports = React.createClass({
     displayName: 'PinnedEventTile',
     propTypes: {
-        mxRoom: React.PropTypes.object.isRequired,
-        mxEvent: React.PropTypes.object.isRequired,
-        onUnpinned: React.PropTypes.func,
+        mxRoom: PropTypes.object.isRequired,
+        mxEvent: PropTypes.object.isRequired,
+        onUnpinned: PropTypes.func,
     },
     onTileClicked: function() {
         dis.dispatch({
diff --git a/src/components/views/rooms/PinnedEventsPanel.js b/src/components/views/rooms/PinnedEventsPanel.js
index a8fb35fcd5..4624b3c051 100644
--- a/src/components/views/rooms/PinnedEventsPanel.js
+++ b/src/components/views/rooms/PinnedEventsPanel.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from "react";
+import PropTypes from 'prop-types';
 import MatrixClientPeg from "../../../MatrixClientPeg";
 import AccessibleButton from "../elements/AccessibleButton";
 import PinnedEventTile from "./PinnedEventTile";
@@ -25,9 +26,9 @@ module.exports = React.createClass({
     displayName: 'PinnedEventsPanel',
     propTypes: {
         // The Room from the js-sdk we're going to show pinned events for
-        room: React.PropTypes.object.isRequired,
+        room: PropTypes.object.isRequired,
 
-        onCancelClick: React.PropTypes.func,
+        onCancelClick: PropTypes.func,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/rooms/PresenceLabel.js b/src/components/views/rooms/PresenceLabel.js
index b6e171100b..22a597b42b 100644
--- a/src/components/views/rooms/PresenceLabel.js
+++ b/src/components/views/rooms/PresenceLabel.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import { _t } from '../../../languageHandler';
 
@@ -27,14 +28,14 @@ module.exports = React.createClass({
     propTypes: {
         // number of milliseconds ago this user was last active.
         // zero = unknown
-        activeAgo: React.PropTypes.number,
+        activeAgo: PropTypes.number,
 
         // if true, activeAgo is an approximation and "Now" should
         // be shown instead
-        currentlyActive: React.PropTypes.bool,
+        currentlyActive: PropTypes.bool,
 
         // offline, online, etc
-        presenceState: React.PropTypes.string,
+        presenceState: PropTypes.string,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/rooms/ReadReceiptMarker.js b/src/components/views/rooms/ReadReceiptMarker.js
index 69ea81cdfa..ea38d07dea 100644
--- a/src/components/views/rooms/ReadReceiptMarker.js
+++ b/src/components/views/rooms/ReadReceiptMarker.js
@@ -18,6 +18,7 @@ limitations under the License.
 
 const React = require('react');
 const ReactDOM = require('react-dom');
+import PropTypes from 'prop-types';
 
 const sdk = require('../../../index');
 
@@ -40,35 +41,35 @@ module.exports = React.createClass({
 
     propTypes: {
         // the RoomMember to show the RR for
-        member: React.PropTypes.object.isRequired,
+        member: PropTypes.object.isRequired,
 
         // number of pixels to offset the avatar from the right of its parent;
         // typically a negative value.
-        leftOffset: React.PropTypes.number,
+        leftOffset: PropTypes.number,
 
         // true to hide the avatar (it will still be animated)
-        hidden: React.PropTypes.bool,
+        hidden: PropTypes.bool,
 
         // don't animate this RR into position
-        suppressAnimation: React.PropTypes.bool,
+        suppressAnimation: PropTypes.bool,
 
         // an opaque object for storing information about this user's RR in
         // this room
-        readReceiptInfo: React.PropTypes.object,
+        readReceiptInfo: PropTypes.object,
 
         // A function which is used to check if the parent panel is being
         // unmounted, to avoid unnecessary work. Should return true if we
         // are being unmounted.
-        checkUnmounting: React.PropTypes.func,
+        checkUnmounting: PropTypes.func,
 
         // callback for clicks on this RR
-        onClick: React.PropTypes.func,
+        onClick: PropTypes.func,
 
         // Timestamp when the receipt was read
-        timestamp: React.PropTypes.number,
+        timestamp: PropTypes.number,
 
         // True to show twelve hour format, false otherwise
-        showTwelveHour: React.PropTypes.bool,
+        showTwelveHour: PropTypes.bool,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js
index aee229c5da..c0644baef7 100644
--- a/src/components/views/rooms/RoomHeader.js
+++ b/src/components/views/rooms/RoomHeader.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
@@ -39,18 +40,18 @@ module.exports = React.createClass({
     displayName: 'RoomHeader',
 
     propTypes: {
-        room: React.PropTypes.object,
-        oobData: React.PropTypes.object,
-        editing: React.PropTypes.bool,
-        saving: React.PropTypes.bool,
-        inRoom: React.PropTypes.bool,
-        collapsedRhs: React.PropTypes.bool,
-        onSettingsClick: React.PropTypes.func,
-        onPinnedClick: React.PropTypes.func,
-        onSaveClick: React.PropTypes.func,
-        onSearchClick: React.PropTypes.func,
-        onLeaveClick: React.PropTypes.func,
-        onCancelClick: React.PropTypes.func,
+        room: PropTypes.object,
+        oobData: PropTypes.object,
+        editing: PropTypes.bool,
+        saving: PropTypes.bool,
+        inRoom: PropTypes.bool,
+        collapsedRhs: PropTypes.bool,
+        onSettingsClick: PropTypes.func,
+        onPinnedClick: PropTypes.func,
+        onSaveClick: PropTypes.func,
+        onSearchClick: PropTypes.func,
+        onLeaveClick: PropTypes.func,
+        onCancelClick: PropTypes.func,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js
index 4784fc116e..9dabeebac0 100644
--- a/src/components/views/rooms/RoomList.js
+++ b/src/components/views/rooms/RoomList.js
@@ -18,6 +18,7 @@ limitations under the License.
 'use strict';
 const React = require("react");
 const ReactDOM = require("react-dom");
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 const GeminiScrollbar = require('react-gemini-scrollbar');
 const MatrixClientPeg = require("../../../MatrixClientPeg");
@@ -52,9 +53,9 @@ module.exports = React.createClass({
     displayName: 'RoomList',
 
     propTypes: {
-        ConferenceHandler: React.PropTypes.any,
-        collapsed: React.PropTypes.bool.isRequired,
-        searchFilter: React.PropTypes.string,
+        ConferenceHandler: PropTypes.any,
+        collapsed: PropTypes.bool.isRequired,
+        searchFilter: PropTypes.string,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/rooms/RoomNameEditor.js b/src/components/views/rooms/RoomNameEditor.js
index c6ebea864e..5c224d79c0 100644
--- a/src/components/views/rooms/RoomNameEditor.js
+++ b/src/components/views/rooms/RoomNameEditor.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const sdk = require('../../../index');
 const MatrixClientPeg = require('../../../MatrixClientPeg');
 import { _t } from '../../../languageHandler';
@@ -25,7 +26,7 @@ module.exports = React.createClass({
     displayName: 'RoomNameEditor',
 
     propTypes: {
-        room: React.PropTypes.object.isRequired,
+        room: PropTypes.object.isRequired,
     },
 
     componentWillMount: function() {
diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js
index 175a3ea552..536093807a 100644
--- a/src/components/views/rooms/RoomPreviewBar.js
+++ b/src/components/views/rooms/RoomPreviewBar.js
@@ -18,6 +18,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const sdk = require('../../../index');
 const MatrixClientPeg = require('../../../MatrixClientPeg');
 
@@ -27,29 +28,29 @@ module.exports = React.createClass({
     displayName: 'RoomPreviewBar',
 
     propTypes: {
-        onJoinClick: React.PropTypes.func,
-        onRejectClick: React.PropTypes.func,
-        onForgetClick: React.PropTypes.func,
+        onJoinClick: PropTypes.func,
+        onRejectClick: PropTypes.func,
+        onForgetClick: PropTypes.func,
 
         // if inviterName is specified, the preview bar will shown an invite to the room.
         // You should also specify onRejectClick if specifiying inviterName
-        inviterName: React.PropTypes.string,
+        inviterName: PropTypes.string,
 
         // If invited by 3rd party invite, the email address the invite was sent to
-        invitedEmail: React.PropTypes.string,
+        invitedEmail: PropTypes.string,
 
         // A standard client/server API error object. If supplied, indicates that the
         // caller was unable to fetch details about the room for the given reason.
-        error: React.PropTypes.object,
+        error: PropTypes.object,
 
-        canPreview: React.PropTypes.bool,
-        spinner: React.PropTypes.bool,
-        room: React.PropTypes.object,
+        canPreview: PropTypes.bool,
+        spinner: PropTypes.bool,
+        room: PropTypes.object,
 
         // The alias that was used to access this room, if appropriate
         // If given, this will be how the room is referred to (eg.
         // in error messages).
-        roomAlias: React.PropTypes.string,
+        roomAlias: PropTypes.string,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js
index 4ac2da2030..0bbf33478d 100644
--- a/src/components/views/rooms/RoomSettings.js
+++ b/src/components/views/rooms/RoomSettings.js
@@ -17,6 +17,7 @@ limitations under the License.
 
 import Promise from 'bluebird';
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t, _td } from '../../../languageHandler';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import sdk from '../../../index';
@@ -60,10 +61,10 @@ const plEventsToShow = {
 
 const BannedUser = React.createClass({
     propTypes: {
-        canUnban: React.PropTypes.bool,
-        member: React.PropTypes.object.isRequired, // js-sdk RoomMember
-        by: React.PropTypes.string.isRequired,
-        reason: React.PropTypes.string,
+        canUnban: PropTypes.bool,
+        member: PropTypes.object.isRequired, // js-sdk RoomMember
+        by: PropTypes.string.isRequired,
+        reason: PropTypes.string,
     },
 
     _onUnbanClick: function() {
@@ -115,8 +116,8 @@ module.exports = React.createClass({
     displayName: 'RoomSettings',
 
     propTypes: {
-        room: React.PropTypes.object.isRequired,
-        onSaveClick: React.PropTypes.func,
+        room: PropTypes.object.isRequired,
+        onSaveClick: PropTypes.func,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js
index 743ec93da9..30cc64ef7a 100644
--- a/src/components/views/rooms/RoomTile.js
+++ b/src/components/views/rooms/RoomTile.js
@@ -19,6 +19,7 @@ limitations under the License.
 
 const React = require('react');
 const ReactDOM = require("react-dom");
+import PropTypes from 'prop-types';
 const classNames = require('classnames');
 const MatrixClientPeg = require('../../../MatrixClientPeg');
 import DMRoomMap from '../../../utils/DMRoomMap';
@@ -34,17 +35,17 @@ module.exports = React.createClass({
     displayName: 'RoomTile',
 
     propTypes: {
-        connectDragSource: React.PropTypes.func,
-        connectDropTarget: React.PropTypes.func,
-        onClick: React.PropTypes.func,
-        isDragging: React.PropTypes.bool,
+        connectDragSource: PropTypes.func,
+        connectDropTarget: PropTypes.func,
+        onClick: PropTypes.func,
+        isDragging: PropTypes.bool,
 
-        room: React.PropTypes.object.isRequired,
-        collapsed: React.PropTypes.bool.isRequired,
-        unread: React.PropTypes.bool.isRequired,
-        highlight: React.PropTypes.bool.isRequired,
-        isInvite: React.PropTypes.bool.isRequired,
-        incomingCall: React.PropTypes.object,
+        room: PropTypes.object.isRequired,
+        collapsed: PropTypes.bool.isRequired,
+        unread: PropTypes.bool.isRequired,
+        highlight: PropTypes.bool.isRequired,
+        isInvite: PropTypes.bool.isRequired,
+        incomingCall: PropTypes.object,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/rooms/RoomTopicEditor.js b/src/components/views/rooms/RoomTopicEditor.js
index 320730f341..8f950d625c 100644
--- a/src/components/views/rooms/RoomTopicEditor.js
+++ b/src/components/views/rooms/RoomTopicEditor.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const sdk = require('../../../index');
 import { _t } from "../../../languageHandler";
 
@@ -24,7 +25,7 @@ module.exports = React.createClass({
     displayName: 'RoomTopicEditor',
 
     propTypes: {
-        room: React.PropTypes.object.isRequired,
+        room: PropTypes.object.isRequired,
     },
 
     componentWillMount: function() {
diff --git a/src/components/views/rooms/SearchResultTile.js b/src/components/views/rooms/SearchResultTile.js
index 1c5cc175ae..9514cc94d2 100644
--- a/src/components/views/rooms/SearchResultTile.js
+++ b/src/components/views/rooms/SearchResultTile.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const sdk = require('../../../index');
 
 module.exports = React.createClass({
@@ -24,15 +25,15 @@ module.exports = React.createClass({
 
     propTypes: {
         // a matrix-js-sdk SearchResult containing the details of this result
-        searchResult: React.PropTypes.object.isRequired,
+        searchResult: PropTypes.object.isRequired,
 
         // a list of strings to be highlighted in the results
-        searchHighlights: React.PropTypes.array,
+        searchHighlights: PropTypes.array,
 
         // href for the highlights in this result
-        resultLink: React.PropTypes.string,
+        resultLink: PropTypes.string,
 
-        onWidgetLoad: React.PropTypes.func,
+        onWidgetLoad: PropTypes.func,
     },
 
     render: function() {
diff --git a/src/components/views/rooms/SearchableEntityList.js b/src/components/views/rooms/SearchableEntityList.js
index c71acdb454..ff75524a5d 100644
--- a/src/components/views/rooms/SearchableEntityList.js
+++ b/src/components/views/rooms/SearchableEntityList.js
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 const React = require('react');
+import PropTypes from 'prop-types';
 const MatrixClientPeg = require("../../../MatrixClientPeg");
 const Modal = require("../../../Modal");
 const sdk = require("../../../index");
@@ -26,12 +27,12 @@ const SearchableEntityList = React.createClass({
     displayName: 'SearchableEntityList',
 
     propTypes: {
-        emptyQueryShowsAll: React.PropTypes.bool,
-        showInputBox: React.PropTypes.bool,
-        onQueryChanged: React.PropTypes.func, // fn(inputText)
-        onSubmit: React.PropTypes.func, // fn(inputText)
-        entities: React.PropTypes.array,
-        truncateAt: React.PropTypes.number,
+        emptyQueryShowsAll: PropTypes.bool,
+        showInputBox: PropTypes.bool,
+        onQueryChanged: PropTypes.func, // fn(inputText)
+        onSubmit: PropTypes.func, // fn(inputText)
+        entities: PropTypes.array,
+        truncateAt: PropTypes.number,
     },
 
     getDefaultProps: function() {
diff --git a/src/components/views/rooms/SimpleRoomHeader.js b/src/components/views/rooms/SimpleRoomHeader.js
index c47d219624..249ba8b93a 100644
--- a/src/components/views/rooms/SimpleRoomHeader.js
+++ b/src/components/views/rooms/SimpleRoomHeader.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import AccessibleButton from '../elements/AccessibleButton';
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
@@ -39,11 +40,11 @@ export default React.createClass({
     displayName: 'SimpleRoomHeader',
 
     propTypes: {
-        title: React.PropTypes.string,
-        onCancelClick: React.PropTypes.func,
+        title: PropTypes.string,
+        onCancelClick: PropTypes.func,
 
         // `src` to a TintableSvg. Optional.
-        icon: React.PropTypes.string,
+        icon: PropTypes.string,
     },
 
     render: function() {
diff --git a/src/components/views/rooms/TopUnreadMessagesBar.js b/src/components/views/rooms/TopUnreadMessagesBar.js
index c32777abad..85a5d3863e 100644
--- a/src/components/views/rooms/TopUnreadMessagesBar.js
+++ b/src/components/views/rooms/TopUnreadMessagesBar.js
@@ -18,6 +18,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 const sdk = require('../../../index');
 
@@ -25,8 +26,8 @@ module.exports = React.createClass({
     displayName: 'TopUnreadMessagesBar',
 
     propTypes: {
-        onScrollUpClick: React.PropTypes.func,
-        onCloseClick: React.PropTypes.func,
+        onScrollUpClick: PropTypes.func,
+        onCloseClick: PropTypes.func,
     },
 
     render: function() {
diff --git a/src/components/views/rooms/UserTile.js b/src/components/views/rooms/UserTile.js
index 0acc71cf48..07a9c00917 100644
--- a/src/components/views/rooms/UserTile.js
+++ b/src/components/views/rooms/UserTile.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 
 const Avatar = require("../../../Avatar");
 const MatrixClientPeg = require('../../../MatrixClientPeg');
@@ -28,7 +29,7 @@ module.exports = React.createClass({
     displayName: 'UserTile',
 
     propTypes: {
-        user: React.PropTypes.any.isRequired, // User
+        user: PropTypes.any.isRequired, // User
     },
 
     render: function() {
diff --git a/src/components/views/settings/AddPhoneNumber.js b/src/components/views/settings/AddPhoneNumber.js
index 10264c0d75..64822ace5f 100644
--- a/src/components/views/settings/AddPhoneNumber.js
+++ b/src/components/views/settings/AddPhoneNumber.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import { _t } from '../../../languageHandler';
 
 import sdk from '../../../index';
@@ -26,8 +27,8 @@ export default withMatrixClient(React.createClass({
     displayName: 'AddPhoneNumber',
 
     propTypes: {
-        matrixClient: React.PropTypes.object.isRequired,
-        onThreepidAdded: React.PropTypes.func,
+        matrixClient: PropTypes.object.isRequired,
+        onThreepidAdded: PropTypes.func,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/settings/ChangeAvatar.js b/src/components/views/settings/ChangeAvatar.js
index a363dc2c60..7164aa4bbe 100644
--- a/src/components/views/settings/ChangeAvatar.js
+++ b/src/components/views/settings/ChangeAvatar.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const MatrixClientPeg = require("../../../MatrixClientPeg");
 const sdk = require('../../../index');
 import { _t } from '../../../languageHandler';
@@ -22,13 +23,13 @@ import { _t } from '../../../languageHandler';
 module.exports = React.createClass({
     displayName: 'ChangeAvatar',
     propTypes: {
-        initialAvatarUrl: React.PropTypes.string,
-        room: React.PropTypes.object,
+        initialAvatarUrl: PropTypes.string,
+        room: PropTypes.object,
         // if false, you need to call changeAvatar.onFileSelected yourself.
-        showUploadSection: React.PropTypes.bool,
-        width: React.PropTypes.number,
-        height: React.PropTypes.number,
-        className: React.PropTypes.string,
+        showUploadSection: PropTypes.bool,
+        width: PropTypes.number,
+        height: PropTypes.number,
+        className: PropTypes.string,
     },
 
     Phases: {
diff --git a/src/components/views/settings/ChangePassword.js b/src/components/views/settings/ChangePassword.js
index 9d8b51c7e8..9cac25e6cc 100644
--- a/src/components/views/settings/ChangePassword.js
+++ b/src/components/views/settings/ChangePassword.js
@@ -17,6 +17,7 @@ limitations under the License.
 'use strict';
 
 const React = require('react');
+import PropTypes from 'prop-types';
 const MatrixClientPeg = require("../../../MatrixClientPeg");
 const Modal = require("../../../Modal");
 const sdk = require("../../../index");
@@ -30,16 +31,16 @@ import sessionStore from '../../../stores/SessionStore';
 module.exports = React.createClass({
     displayName: 'ChangePassword',
     propTypes: {
-        onFinished: React.PropTypes.func,
-        onError: React.PropTypes.func,
-        onCheckPassword: React.PropTypes.func,
-        rowClassName: React.PropTypes.string,
-        rowLabelClassName: React.PropTypes.string,
-        rowInputClassName: React.PropTypes.string,
-        buttonClassName: React.PropTypes.string,
-        confirm: React.PropTypes.bool,
+        onFinished: PropTypes.func,
+        onError: PropTypes.func,
+        onCheckPassword: PropTypes.func,
+        rowClassName: PropTypes.string,
+        rowLabelClassName: PropTypes.string,
+        rowInputClassName: PropTypes.string,
+        buttonClassName: PropTypes.string,
+        confirm: PropTypes.bool,
         // Whether to autoFocus the new password input
-        autoFocusNewPasswordInput: React.PropTypes.bool,
+        autoFocusNewPasswordInput: PropTypes.bool,
     },
 
     Phases: {
diff --git a/src/components/views/settings/DevicesPanel.js b/src/components/views/settings/DevicesPanel.js
index 413594d698..f0fec2cf63 100644
--- a/src/components/views/settings/DevicesPanel.js
+++ b/src/components/views/settings/DevicesPanel.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import classNames from 'classnames';
 
 import sdk from '../../../index';
@@ -207,5 +208,5 @@ export default class DevicesPanel extends React.Component {
 
 DevicesPanel.displayName = 'MemberDeviceInfo';
 DevicesPanel.propTypes = {
-    className: React.PropTypes.string,
+    className: PropTypes.string,
 };
diff --git a/src/components/views/settings/DevicesPanelEntry.js b/src/components/views/settings/DevicesPanelEntry.js
index e5f9dcac46..4c08a938c7 100644
--- a/src/components/views/settings/DevicesPanelEntry.js
+++ b/src/components/views/settings/DevicesPanelEntry.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 import sdk from '../../../index';
 import { _t } from '../../../languageHandler';
@@ -88,8 +89,8 @@ export default class DevicesPanelEntry extends React.Component {
 }
 
 DevicesPanelEntry.propTypes = {
-    device: React.PropTypes.object.isRequired,
-    onDeviceToggled: React.PropTypes.func,
+    device: PropTypes.object.isRequired,
+    onDeviceToggled: PropTypes.func,
 };
 
 DevicesPanelEntry.defaultProps = {
diff --git a/src/components/views/voip/CallPreview.js b/src/components/views/voip/CallPreview.js
index 132e29bd34..272e6feb37 100644
--- a/src/components/views/voip/CallPreview.js
+++ b/src/components/views/voip/CallPreview.js
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import React from 'react';
+import PropTypes from 'prop-types';
 import RoomViewStore from '../../../stores/RoomViewStore';
 import CallHandler from '../../../CallHandler';
 import dis from '../../../dispatcher';
@@ -27,7 +28,7 @@ module.exports = React.createClass({
         // A Conference Handler implementation
         // Must have a function signature:
         //  getConferenceCallForRoom(roomId: string): MatrixCall
-        ConferenceHandler: React.PropTypes.object,
+        ConferenceHandler: PropTypes.object,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/voip/CallView.js b/src/components/views/voip/CallView.js
index 37d111be93..47e8ae22db 100644
--- a/src/components/views/voip/CallView.js
+++ b/src/components/views/voip/CallView.js
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 import React from 'react';
+import PropTypes from 'prop-types';
 import dis from '../../../dispatcher';
 import CallHandler from '../../../CallHandler';
 import sdk from '../../../index';
@@ -26,25 +27,25 @@ module.exports = React.createClass({
     propTypes: {
         // js-sdk room object. If set, we will only show calls for the given
         // room; if not, we will show any active call.
-        room: React.PropTypes.object,
+        room: PropTypes.object,
 
         // A Conference Handler implementation
         // Must have a function signature:
         //  getConferenceCallForRoom(roomId: string): MatrixCall
-        ConferenceHandler: React.PropTypes.object,
+        ConferenceHandler: PropTypes.object,
 
         // maxHeight style attribute for the video panel
-        maxVideoHeight: React.PropTypes.number,
+        maxVideoHeight: PropTypes.number,
 
         // a callback which is called when the user clicks on the video div
-        onClick: React.PropTypes.func,
+        onClick: PropTypes.func,
 
         // a callback which is called when the content in the callview changes
         // in a way that is likely to cause a resize.
-        onResize: React.PropTypes.func,
+        onResize: PropTypes.func,
 
         // render ongoing audio call details - useful when in LeftPanel
-        showVoice: React.PropTypes.bool,
+        showVoice: PropTypes.bool,
     },
 
     getInitialState: function() {
diff --git a/src/components/views/voip/IncomingCallBox.js b/src/components/views/voip/IncomingCallBox.js
index c12924791a..8d75029baa 100644
--- a/src/components/views/voip/IncomingCallBox.js
+++ b/src/components/views/voip/IncomingCallBox.js
@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 import React from 'react';
+import PropTypes from 'prop-types';
 import MatrixClientPeg from '../../../MatrixClientPeg';
 import dis from '../../../dispatcher';
 import { _t } from '../../../languageHandler';
@@ -22,7 +23,7 @@ module.exports = React.createClass({
     displayName: 'IncomingCallBox',
 
     propTypes: {
-        incomingCall: React.PropTypes.object,
+        incomingCall: PropTypes.object,
     },
 
     onAnswerClick: function() {
diff --git a/src/components/views/voip/VideoFeed.js b/src/components/views/voip/VideoFeed.js
index f955df62d9..23dc236d62 100644
--- a/src/components/views/voip/VideoFeed.js
+++ b/src/components/views/voip/VideoFeed.js
@@ -17,17 +17,18 @@ limitations under the License.
 'use strict';
 
 import React from 'react';
+import PropTypes from 'prop-types';
 
 module.exports = React.createClass({
     displayName: 'VideoFeed',
 
     propTypes: {
         // maxHeight style attribute for the video element
-        maxHeight: React.PropTypes.number,
+        maxHeight: PropTypes.number,
 
         // a callback which is called when the video element is resized
         // due to a change in video metadata
-        onResize: React.PropTypes.func,
+        onResize: PropTypes.func,
     },
 
     componentDidMount() {
diff --git a/src/components/views/voip/VideoView.js b/src/components/views/voip/VideoView.js
index 44e7a47f02..1820514129 100644
--- a/src/components/views/voip/VideoView.js
+++ b/src/components/views/voip/VideoView.js
@@ -18,6 +18,7 @@ limitations under the License.
 
 import React from 'react';
 import ReactDOM from 'react-dom';
+import PropTypes from 'prop-types';
 import classNames from 'classnames';
 
 import sdk from '../../../index';
@@ -30,14 +31,14 @@ module.exports = React.createClass({
 
     propTypes: {
         // maxHeight style attribute for the video element
-        maxHeight: React.PropTypes.number,
+        maxHeight: PropTypes.number,
 
         // a callback which is called when the user clicks on the video div
-        onClick: React.PropTypes.func,
+        onClick: PropTypes.func,
 
         // a callback which is called when the video element is resized due to
         // a change in video metadata
-        onResize: React.PropTypes.func,
+        onResize: PropTypes.func,
     },
 
     componentDidMount: function() {
diff --git a/src/wrappers/withMatrixClient.js b/src/wrappers/withMatrixClient.js
index 2333358817..7be3b0561d 100644
--- a/src/wrappers/withMatrixClient.js
+++ b/src/wrappers/withMatrixClient.js
@@ -17,6 +17,7 @@ limitations under the License.
 
 import * as Matrix from 'matrix-js-sdk';
 import React from 'react';
+import PropTypes from 'prop-types';
 
 /**
  * Wraps a react class, pulling the MatrixClient from the context and adding it
@@ -30,7 +31,7 @@ export default function(WrappedComponent) {
         displayName: "withMatrixClient<" + WrappedComponent.displayName + ">",
 
         contextTypes: {
-            matrixClient: React.PropTypes.instanceOf(Matrix.MatrixClient).isRequired,
+            matrixClient: PropTypes.instanceOf(Matrix.MatrixClient).isRequired,
         },
 
         render: function() {