From 8f66126b1010e0aaaa8b5f2a2f4ea8a28824e2b7 Mon Sep 17 00:00:00 2001
From: Renaud Chaput <renchap@gmail.com>
Date: Tue, 23 May 2023 10:52:27 +0200
Subject: [PATCH] Use the new JSX transform (#25064)

---
 .eslintrc.js                                  |  8 +++++++
 .../__tests__/autosuggest_emoji-test.jsx      |  1 -
 .../components/__tests__/avatar-test.jsx      |  1 -
 .../__tests__/avatar_overlay-test.jsx         |  1 -
 .../components/__tests__/button-test.jsx      |  1 -
 .../__tests__/display_name-test.jsx           |  1 -
 .../mastodon/components/account.jsx           |  1 -
 .../mastodon/components/admin/Counter.jsx     | 16 ++++++-------
 .../mastodon/components/admin/Dimension.jsx   |  4 ++--
 .../components/admin/ReportReasonSelector.jsx |  8 +++----
 .../mastodon/components/admin/Retention.jsx   |  4 ++--
 .../mastodon/components/admin/Trends.jsx      |  4 ++--
 .../mastodon/components/animated_number.tsx   |  2 +-
 .../mastodon/components/attachment_list.jsx   |  1 -
 .../mastodon/components/autosuggest_emoji.jsx |  4 ++--
 .../components/autosuggest_hashtag.jsx        |  4 ++--
 .../mastodon/components/autosuggest_input.jsx |  1 -
 .../components/autosuggest_textarea.jsx       |  1 -
 app/javascript/mastodon/components/avatar.tsx |  2 --
 .../mastodon/components/avatar_composite.jsx  |  4 ++--
 .../mastodon/components/avatar_overlay.tsx    |  2 --
 .../mastodon/components/blurhash.tsx          |  4 ++--
 app/javascript/mastodon/components/button.jsx |  4 ++--
 app/javascript/mastodon/components/check.tsx  |  2 --
 app/javascript/mastodon/components/column.jsx |  4 ++--
 .../components/column_back_button.jsx         |  4 ++--
 .../components/column_back_button_slim.jsx    |  1 -
 .../mastodon/components/column_header.jsx     |  4 ++--
 .../mastodon/components/common_counter.jsx    |  1 -
 .../components/dismissable_banner.jsx         |  4 ++--
 app/javascript/mastodon/components/domain.tsx |  2 +-
 .../mastodon/components/dropdown_menu.jsx     | 12 +++++-----
 .../components/edited_timestamp/index.jsx     |  4 ++--
 .../mastodon/components/error_boundary.jsx    |  4 ++--
 app/javascript/mastodon/components/gifv.tsx   |  2 +-
 .../mastodon/components/hashtag.jsx           |  6 ++---
 app/javascript/mastodon/components/icon.tsx   |  2 --
 .../mastodon/components/icon_button.tsx       |  8 +++----
 .../mastodon/components/icon_with_badge.tsx   |  2 --
 .../mastodon/components/inline_account.jsx    |  4 ++--
 .../intersection_observer_article.jsx         |  8 +++----
 .../mastodon/components/load_gap.jsx          |  4 ++--
 .../mastodon/components/load_more.jsx         |  4 ++--
 .../mastodon/components/load_pending.jsx      |  4 ++--
 .../mastodon/components/loading_indicator.jsx |  1 -
 app/javascript/mastodon/components/logo.tsx   |  2 --
 .../mastodon/components/media_attachments.jsx |  1 -
 .../mastodon/components/media_gallery.jsx     |  6 ++---
 .../mastodon/components/modal_root.jsx        |  4 ++--
 .../mastodon/components/navigation_portal.jsx |  4 ++--
 .../components/not_signed_in_indicator.tsx    |  2 --
 .../picture_in_picture_placeholder.jsx        |  4 ++--
 app/javascript/mastodon/components/poll.jsx   |  1 -
 .../mastodon/components/radio_button.tsx      |  2 --
 .../components/regeneration_indicator.jsx     |  1 -
 .../components/relative_timestamp.tsx         |  4 ++--
 .../mastodon/components/scrollable_list.jsx   | 12 +++++-----
 .../mastodon/components/server_banner.jsx     |  4 ++--
 .../mastodon/components/server_hero_image.tsx |  2 +-
 .../mastodon/components/short_number.jsx      |  4 ++--
 .../mastodon/components/skeleton.tsx          |  2 --
 app/javascript/mastodon/components/status.jsx |  1 -
 .../mastodon/components/status_action_bar.jsx |  1 -
 .../mastodon/components/status_content.jsx    |  6 ++---
 .../mastodon/components/status_list.jsx       |  1 -
 .../mastodon/components/timeline_hint.tsx     |  2 --
 .../mastodon/components/verified_badge.tsx    |  2 --
 .../mastodon/containers/account_container.jsx |  1 -
 .../mastodon/containers/admin_component.jsx   |  4 ++--
 .../mastodon/containers/compose_container.jsx |  4 ++--
 .../mastodon/containers/domain_container.jsx  |  1 -
 .../mastodon/containers/mastodon.jsx          |  4 ++--
 .../mastodon/containers/media_container.jsx   |  2 +-
 .../mastodon/containers/status_container.jsx  |  1 -
 .../mastodon/features/about/index.jsx         |  6 ++---
 .../account/components/account_note.jsx       |  4 ++--
 .../account/components/featured_tags.jsx      |  1 -
 .../components/follow_request_note.jsx        |  1 -
 .../features/account/components/header.jsx    |  6 ++---
 .../mastodon/features/account/navigation.jsx  |  4 ++--
 .../account_gallery/components/media_item.jsx |  1 -
 .../features/account_gallery/index.jsx        |  1 -
 .../account_timeline/components/header.jsx    |  1 -
 .../components/limited_account_hint.jsx       |  4 ++--
 .../components/memorial_note.jsx              |  1 -
 .../components/moved_note.jsx                 |  1 -
 .../containers/header_container.jsx           |  1 -
 .../features/account_timeline/index.jsx       |  1 -
 .../mastodon/features/audio/index.jsx         |  4 ++--
 .../mastodon/features/blocks/index.jsx        |  1 -
 .../features/bookmarked_statuses/index.jsx    |  1 -
 .../closed_registrations_modal/index.jsx      |  1 -
 .../components/column_settings.jsx            |  4 ++--
 .../features/community_timeline/index.jsx     |  4 ++--
 .../compose/components/action_bar.jsx         |  4 ++--
 .../components/autosuggest_account.jsx        |  1 -
 .../compose/components/character_counter.jsx  |  4 ++--
 .../compose/components/compose_form.jsx       |  1 -
 .../components/emoji_picker_dropdown.jsx      | 10 ++++----
 .../compose/components/language_dropdown.jsx  |  6 ++---
 .../compose/components/navigation_bar.jsx     |  1 -
 .../compose/components/poll_button.jsx        |  4 ++--
 .../features/compose/components/poll_form.jsx |  4 ++--
 .../compose/components/privacy_dropdown.jsx   |  6 ++---
 .../compose/components/reply_indicator.jsx    |  1 -
 .../features/compose/components/search.jsx    |  4 ++--
 .../compose/components/search_results.jsx     |  1 -
 .../compose/components/text_icon_button.jsx   |  4 ++--
 .../features/compose/components/upload.jsx    |  1 -
 .../compose/components/upload_button.jsx      |  1 -
 .../compose/components/upload_form.jsx        |  1 -
 .../compose/components/upload_progress.jsx    |  4 ++--
 .../features/compose/components/warning.jsx   |  4 ++--
 .../containers/sensitive_button_container.jsx |  4 ++--
 .../compose/containers/warning_container.jsx  |  1 -
 .../mastodon/features/compose/index.jsx       |  4 ++--
 .../components/conversation.jsx               |  1 -
 .../components/conversations_list.jsx         |  1 -
 .../features/direct_timeline/index.jsx        |  4 ++--
 .../directory/components/account_card.jsx     |  1 -
 .../mastodon/features/directory/index.jsx     |  4 ++--
 .../mastodon/features/domain_blocks/index.jsx |  1 -
 .../features/explore/components/story.jsx     |  8 +++----
 .../mastodon/features/explore/index.jsx       |  4 ++--
 .../mastodon/features/explore/links.jsx       |  4 ++--
 .../mastodon/features/explore/results.jsx     |  8 +++----
 .../mastodon/features/explore/statuses.jsx    |  4 ++--
 .../mastodon/features/explore/suggestions.jsx |  4 ++--
 .../mastodon/features/explore/tags.jsx        |  4 ++--
 .../features/favourited_statuses/index.jsx    |  1 -
 .../mastodon/features/favourites/index.jsx    |  1 -
 .../features/filters/added_to_filter.jsx      | 16 ++++++-------
 .../features/filters/select_filter.jsx        |  8 +++----
 .../components/account_authorize.jsx          |  1 -
 .../features/follow_requests/index.jsx        |  1 -
 .../mastodon/features/followed_tags/index.jsx |  1 -
 .../mastodon/features/followers/index.jsx     |  1 -
 .../mastodon/features/following/index.jsx     |  1 -
 .../components/announcements.jsx              |  4 ++--
 .../getting_started/components/trends.jsx     |  1 -
 .../features/getting_started/index.jsx        |  1 -
 .../components/column_settings.jsx            |  4 ++--
 .../features/hashtag_timeline/index.jsx       |  4 ++--
 .../components/column_settings.jsx            |  4 ++--
 .../mastodon/features/home_timeline/index.jsx |  4 ++--
 .../features/interaction_modal/index.jsx      |  6 ++---
 .../features/keyboard_shortcuts/index.jsx     |  1 -
 .../list_adder/components/account.jsx         |  1 -
 .../features/list_adder/components/list.jsx   |  1 -
 .../mastodon/features/list_adder/index.jsx    |  1 -
 .../list_editor/components/account.jsx        |  1 -
 .../list_editor/components/edit_list_form.jsx |  4 ++--
 .../list_editor/components/search.jsx         |  4 ++--
 .../mastodon/features/list_editor/index.jsx   |  1 -
 .../mastodon/features/list_timeline/index.jsx |  4 ++--
 .../lists/components/new_list_form.jsx        |  4 ++--
 .../mastodon/features/lists/index.jsx         |  1 -
 .../mastodon/features/mutes/index.jsx         |  1 -
 .../components/clear_column_button.jsx        |  4 ++--
 .../components/column_settings.jsx            |  4 ++--
 .../notifications/components/filter_bar.jsx   |  4 ++--
 .../components/follow_request.jsx             |  6 ++---
 .../components/grant_permission_button.jsx    |  4 ++--
 .../notifications/components/notification.jsx |  1 -
 .../notifications_permission_banner.jsx       |  4 ++--
 .../notifications/components/report.jsx       |  2 +-
 .../components/setting_toggle.jsx             |  4 ++--
 .../mastodon/features/notifications/index.jsx |  4 ++--
 .../components/arrow_small_right.jsx          |  2 --
 .../components/progress_indicator.jsx         |  6 ++---
 .../features/onboarding/components/step.jsx   |  1 -
 .../mastodon/features/onboarding/follows.jsx  |  4 ++--
 .../mastodon/features/onboarding/index.jsx    |  1 -
 .../mastodon/features/onboarding/share.jsx    |  8 +++----
 .../picture_in_picture/components/footer.jsx  |  1 -
 .../picture_in_picture/components/header.jsx  |  1 -
 .../features/picture_in_picture/index.jsx     |  4 ++--
 .../features/pinned_statuses/index.jsx        |  1 -
 .../features/privacy_policy/index.jsx         |  4 ++--
 .../components/column_settings.jsx            |  4 ++--
 .../features/public_timeline/index.jsx        |  4 ++--
 .../mastodon/features/reblogs/index.jsx       |  1 -
 .../mastodon/features/report/category.jsx     |  8 +++----
 .../mastodon/features/report/comment.jsx      | 12 +++++-----
 .../features/report/components/option.jsx     |  4 ++--
 .../report/components/status_check_box.jsx    |  4 ++--
 .../mastodon/features/report/rules.jsx        |  8 +++----
 .../mastodon/features/report/statuses.jsx     |  8 +++----
 .../mastodon/features/report/thanks.jsx       | 12 +++++-----
 .../features/standalone/compose/index.jsx     |  4 ++--
 .../features/status/components/action_bar.jsx |  4 ++--
 .../features/status/components/card.jsx       |  4 ++--
 .../status/components/detailed_status.jsx     | 24 +++++++++----------
 .../mastodon/features/status/index.jsx        |  1 -
 .../subscribed_languages_modal/index.jsx      |  1 -
 .../ui/components/__tests__/column-test.jsx   |  1 -
 .../features/ui/components/actions_modal.jsx  |  1 -
 .../features/ui/components/audio_modal.jsx    |  1 -
 .../features/ui/components/block_modal.jsx    |  4 ++--
 .../features/ui/components/boost_modal.jsx    |  1 -
 .../features/ui/components/bundle.jsx         |  4 ++--
 .../ui/components/bundle_column_error.jsx     |  8 +++----
 .../ui/components/bundle_modal_error.jsx      |  4 ++--
 .../features/ui/components/column.jsx         |  4 ++--
 .../features/ui/components/column_header.jsx  |  4 ++--
 .../features/ui/components/column_link.jsx    |  1 -
 .../features/ui/components/column_loading.jsx |  1 -
 .../ui/components/column_subheading.jsx       |  1 -
 .../features/ui/components/columns_area.jsx   |  4 ++--
 .../ui/components/compare_history_modal.jsx   |  8 +++----
 .../features/ui/components/compose_panel.jsx  | 12 +++++-----
 .../ui/components/confirmation_modal.jsx      |  4 ++--
 .../ui/components/disabled_account_banner.jsx |  4 ++--
 .../features/ui/components/drawer_loading.jsx |  2 --
 .../features/ui/components/embed_modal.jsx    |  1 -
 .../features/ui/components/filter_modal.jsx   |  1 -
 .../ui/components/focal_point_modal.jsx       |  8 +++----
 .../follow_requests_column_link.jsx           |  4 ++--
 .../features/ui/components/header.jsx         |  4 ++--
 .../features/ui/components/image_loader.jsx   |  2 +-
 .../features/ui/components/image_modal.jsx    |  4 ++--
 .../features/ui/components/link_footer.jsx    |  4 ++--
 .../features/ui/components/list_panel.jsx     |  1 -
 .../features/ui/components/media_modal.jsx    |  1 -
 .../features/ui/components/modal_loading.jsx  |  2 --
 .../features/ui/components/modal_root.jsx     |  4 ++--
 .../features/ui/components/mute_modal.jsx     |  4 ++--
 .../ui/components/navigation_panel.jsx        | 12 +++++-----
 .../features/ui/components/report_modal.jsx   |  1 -
 .../features/ui/components/sign_in_banner.jsx |  2 +-
 .../features/ui/components/upload_area.jsx    |  4 ++--
 .../features/ui/components/video_modal.jsx    |  1 -
 .../features/ui/components/zoomable_image.jsx |  8 +++----
 app/javascript/mastodon/features/ui/index.jsx |  6 ++---
 .../features/ui/util/react_router_helpers.jsx |  8 +++----
 .../features/ui/util/reduced_motion.jsx       |  4 ++--
 .../mastodon/features/video/index.jsx         |  4 ++--
 app/javascript/mastodon/main.jsx              |  1 -
 app/javascript/mastodon/utils/icons.jsx       |  2 --
 babel.config.js                               |  1 +
 tsconfig.json                                 |  2 +-
 241 files changed, 366 insertions(+), 473 deletions(-)

diff --git a/.eslintrc.js b/.eslintrc.js
index 1800daa55d..1dbfd1d3ed 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -101,7 +101,12 @@ module.exports = {
     'react/jsx-equals-spacing': 'error',
     'react/jsx-no-bind': 'error',
     'react/jsx-no-target-blank': 'off',
+    'react/jsx-tag-spacing': 'error',
+    'react/jsx-uses-react': 'off', // not needed with new JSX transform
+    'react/jsx-wrap-multilines': 'error',
+    'react/no-deprecated': 'off',
     'react/no-unknown-property': 'off',
+    'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
     'react/self-closing-comp': 'error',
 
     // recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/index.js
@@ -339,6 +344,9 @@ module.exports = {
         'import/no-default-export': 'warn',
         'react/prefer-stateless-function': 'warn',
         'react/function-component-definition': ['error', { namedComponents: 'arrow-function' }],
+        'react/jsx-uses-react': 'off', // not needed with new JSX transform
+        'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
+        'react/prop-types': 'off',
       },
     },
     {
diff --git a/app/javascript/mastodon/components/__tests__/autosuggest_emoji-test.jsx b/app/javascript/mastodon/components/__tests__/autosuggest_emoji-test.jsx
index 05616e4448..80aa33a187 100644
--- a/app/javascript/mastodon/components/__tests__/autosuggest_emoji-test.jsx
+++ b/app/javascript/mastodon/components/__tests__/autosuggest_emoji-test.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import renderer from 'react-test-renderer';
 import AutosuggestEmoji from '../autosuggest_emoji';
 
diff --git a/app/javascript/mastodon/components/__tests__/avatar-test.jsx b/app/javascript/mastodon/components/__tests__/avatar-test.jsx
index 5a72fc19a1..b20c6f4e39 100644
--- a/app/javascript/mastodon/components/__tests__/avatar-test.jsx
+++ b/app/javascript/mastodon/components/__tests__/avatar-test.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import renderer from 'react-test-renderer';
 import { fromJS } from 'immutable';
 import { Avatar } from '../avatar';
diff --git a/app/javascript/mastodon/components/__tests__/avatar_overlay-test.jsx b/app/javascript/mastodon/components/__tests__/avatar_overlay-test.jsx
index ea75dab574..c03a9aa9d0 100644
--- a/app/javascript/mastodon/components/__tests__/avatar_overlay-test.jsx
+++ b/app/javascript/mastodon/components/__tests__/avatar_overlay-test.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import renderer from 'react-test-renderer';
 import { fromJS } from 'immutable';
 import { AvatarOverlay } from '../avatar_overlay';
diff --git a/app/javascript/mastodon/components/__tests__/button-test.jsx b/app/javascript/mastodon/components/__tests__/button-test.jsx
index f5a649f70e..82d307e843 100644
--- a/app/javascript/mastodon/components/__tests__/button-test.jsx
+++ b/app/javascript/mastodon/components/__tests__/button-test.jsx
@@ -1,5 +1,4 @@
 import { render, fireEvent, screen } from '@testing-library/react';
-import React from 'react';
 import renderer from 'react-test-renderer';
 import Button from '../button';
 
diff --git a/app/javascript/mastodon/components/__tests__/display_name-test.jsx b/app/javascript/mastodon/components/__tests__/display_name-test.jsx
index afb6c4758a..a1e6da87ad 100644
--- a/app/javascript/mastodon/components/__tests__/display_name-test.jsx
+++ b/app/javascript/mastodon/components/__tests__/display_name-test.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import renderer from 'react-test-renderer';
 import { fromJS }  from 'immutable';
 import { DisplayName } from '../display_name';
diff --git a/app/javascript/mastodon/components/account.jsx b/app/javascript/mastodon/components/account.jsx
index 08dfb4793d..f40f5324dc 100644
--- a/app/javascript/mastodon/components/account.jsx
+++ b/app/javascript/mastodon/components/account.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import { Avatar } from './avatar';
diff --git a/app/javascript/mastodon/components/admin/Counter.jsx b/app/javascript/mastodon/components/admin/Counter.jsx
index 569f8628a9..5eb8369582 100644
--- a/app/javascript/mastodon/components/admin/Counter.jsx
+++ b/app/javascript/mastodon/components/admin/Counter.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import api from 'mastodon/api';
 import { FormattedNumber } from 'react-intl';
@@ -24,7 +24,7 @@ const percIncrease = (a, b) => {
   return percent;
 };
 
-export default class Counter extends React.PureComponent {
+export default class Counter extends PureComponent {
 
   static propTypes = {
     measure: PropTypes.string.isRequired,
@@ -62,25 +62,25 @@ export default class Counter extends React.PureComponent {
 
     if (loading) {
       content = (
-        <React.Fragment>
+        <Fragment>
           <span className='sparkline__value__total'><Skeleton width={43} /></span>
           <span className='sparkline__value__change'><Skeleton width={43} /></span>
-        </React.Fragment>
+        </Fragment>
       );
     } else {
       const measure = data[0];
       const percentChange = measure.previous_total && percIncrease(measure.previous_total * 1, measure.total * 1);
 
       content = (
-        <React.Fragment>
+        <Fragment>
           <span className='sparkline__value__total'>{measure.human_value || <FormattedNumber value={measure.total} />}</span>
           {measure.previous_total && (<span className={classNames('sparkline__value__change', { positive: percentChange > 0, negative: percentChange < 0 })}>{percentChange > 0 && '+'}<FormattedNumber value={percentChange} style='percent' /></span>)}
-        </React.Fragment>
+        </Fragment>
       );
     }
 
     const inner = (
-      <React.Fragment>
+      <Fragment>
         <div className='sparkline__value'>
           {content}
         </div>
@@ -96,7 +96,7 @@ export default class Counter extends React.PureComponent {
             </Sparklines>
           )}
         </div>
-      </React.Fragment>
+      </Fragment>
     );
 
     if (href) {
diff --git a/app/javascript/mastodon/components/admin/Dimension.jsx b/app/javascript/mastodon/components/admin/Dimension.jsx
index 3005c15ae9..1b4203a183 100644
--- a/app/javascript/mastodon/components/admin/Dimension.jsx
+++ b/app/javascript/mastodon/components/admin/Dimension.jsx
@@ -1,11 +1,11 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import api from 'mastodon/api';
 import { FormattedNumber } from 'react-intl';
 import { roundTo10 } from 'mastodon/utils/numbers';
 import { Skeleton } from 'mastodon/components/skeleton';
 
-export default class Dimension extends React.PureComponent {
+export default class Dimension extends PureComponent {
 
   static propTypes = {
     dimension: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx b/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx
index cd14dac4e3..ae0bfeef79 100644
--- a/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx
+++ b/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import api from 'mastodon/api';
 import { injectIntl, defineMessages } from 'react-intl';
@@ -10,7 +10,7 @@ const messages = defineMessages({
   violation: { id: 'report.categories.violation', defaultMessage: 'Content violates one or more server rules' },
 });
 
-class Category extends React.PureComponent {
+class Category extends PureComponent {
 
   static propTypes = {
     id: PropTypes.string.isRequired,
@@ -52,7 +52,7 @@ class Category extends React.PureComponent {
 
 }
 
-class Rule extends React.PureComponent {
+class Rule extends PureComponent {
 
   static propTypes = {
     id: PropTypes.string.isRequired,
@@ -84,7 +84,7 @@ class Rule extends React.PureComponent {
 
 }
 
-class ReportReasonSelector extends React.PureComponent {
+class ReportReasonSelector extends PureComponent {
 
   static propTypes = {
     id: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/components/admin/Retention.jsx b/app/javascript/mastodon/components/admin/Retention.jsx
index f312a45eb2..e51e0d15bd 100644
--- a/app/javascript/mastodon/components/admin/Retention.jsx
+++ b/app/javascript/mastodon/components/admin/Retention.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import api from 'mastodon/api';
 import { FormattedMessage, FormattedNumber, FormattedDate } from 'react-intl';
@@ -14,7 +14,7 @@ const dateForCohort = cohort => {
   }
 };
 
-export default class Retention extends React.PureComponent {
+export default class Retention extends PureComponent {
 
   static propTypes = {
     start_at: PropTypes.string,
diff --git a/app/javascript/mastodon/components/admin/Trends.jsx b/app/javascript/mastodon/components/admin/Trends.jsx
index d01b8437ed..30b781e7cb 100644
--- a/app/javascript/mastodon/components/admin/Trends.jsx
+++ b/app/javascript/mastodon/components/admin/Trends.jsx
@@ -1,11 +1,11 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import api from 'mastodon/api';
 import { FormattedMessage } from 'react-intl';
 import classNames from 'classnames';
 import Hashtag from 'mastodon/components/hashtag';
 
-export default class Trends extends React.PureComponent {
+export default class Trends extends PureComponent {
 
   static propTypes = {
     limit: PropTypes.number.isRequired,
diff --git a/app/javascript/mastodon/components/animated_number.tsx b/app/javascript/mastodon/components/animated_number.tsx
index b6b073161b..ad985a29ea 100644
--- a/app/javascript/mastodon/components/animated_number.tsx
+++ b/app/javascript/mastodon/components/animated_number.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useState } from 'react';
+import { useCallback, useState } from 'react';
 
 import { TransitionMotion, spring } from 'react-motion';
 
diff --git a/app/javascript/mastodon/components/attachment_list.jsx b/app/javascript/mastodon/components/attachment_list.jsx
index 3354025c4a..502f68c7e2 100644
--- a/app/javascript/mastodon/components/attachment_list.jsx
+++ b/app/javascript/mastodon/components/attachment_list.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/components/autosuggest_emoji.jsx b/app/javascript/mastodon/components/autosuggest_emoji.jsx
index 4937e4d984..8afbdd9cb5 100644
--- a/app/javascript/mastodon/components/autosuggest_emoji.jsx
+++ b/app/javascript/mastodon/components/autosuggest_emoji.jsx
@@ -1,9 +1,9 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import unicodeMapping from '../features/emoji/emoji_unicode_mapping_light';
 import { assetHost } from 'mastodon/utils/config';
 
-export default class AutosuggestEmoji extends React.PureComponent {
+export default class AutosuggestEmoji extends PureComponent {
 
   static propTypes = {
     emoji: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/components/autosuggest_hashtag.jsx b/app/javascript/mastodon/components/autosuggest_hashtag.jsx
index 9e9d888f83..4fd23ec9a8 100644
--- a/app/javascript/mastodon/components/autosuggest_hashtag.jsx
+++ b/app/javascript/mastodon/components/autosuggest_hashtag.jsx
@@ -1,9 +1,9 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ShortNumber from 'mastodon/components/short_number';
 import { FormattedMessage } from 'react-intl';
 
-export default class AutosuggestHashtag extends React.PureComponent {
+export default class AutosuggestHashtag extends PureComponent {
 
   static propTypes = {
     tag: PropTypes.shape({
diff --git a/app/javascript/mastodon/components/autosuggest_input.jsx b/app/javascript/mastodon/components/autosuggest_input.jsx
index 218faabb79..2e0e8002be 100644
--- a/app/javascript/mastodon/components/autosuggest_input.jsx
+++ b/app/javascript/mastodon/components/autosuggest_input.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import AutosuggestAccountContainer from '../features/compose/containers/autosuggest_account_container';
 import AutosuggestEmoji from './autosuggest_emoji';
 import AutosuggestHashtag from './autosuggest_hashtag';
diff --git a/app/javascript/mastodon/components/autosuggest_textarea.jsx b/app/javascript/mastodon/components/autosuggest_textarea.jsx
index 50cc24b002..4c9091b333 100644
--- a/app/javascript/mastodon/components/autosuggest_textarea.jsx
+++ b/app/javascript/mastodon/components/autosuggest_textarea.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import AutosuggestAccountContainer from '../features/compose/containers/autosuggest_account_container';
 import AutosuggestEmoji from './autosuggest_emoji';
 import AutosuggestHashtag from './autosuggest_hashtag';
diff --git a/app/javascript/mastodon/components/avatar.tsx b/app/javascript/mastodon/components/avatar.tsx
index 2b46b05d65..8e5e165fe7 100644
--- a/app/javascript/mastodon/components/avatar.tsx
+++ b/app/javascript/mastodon/components/avatar.tsx
@@ -1,5 +1,3 @@
-import * as React from 'react';
-
 import classNames from 'classnames';
 
 import { useHovering } from '../../hooks/useHovering';
diff --git a/app/javascript/mastodon/components/avatar_composite.jsx b/app/javascript/mastodon/components/avatar_composite.jsx
index e1fae95dc0..5b15e2a732 100644
--- a/app/javascript/mastodon/components/avatar_composite.jsx
+++ b/app/javascript/mastodon/components/avatar_composite.jsx
@@ -1,10 +1,10 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { autoPlayGif } from '../initial_state';
 import { Avatar } from './avatar';
 
-export default class AvatarComposite extends React.PureComponent {
+export default class AvatarComposite extends PureComponent {
 
   static propTypes = {
     accounts: ImmutablePropTypes.list.isRequired,
diff --git a/app/javascript/mastodon/components/avatar_overlay.tsx b/app/javascript/mastodon/components/avatar_overlay.tsx
index d1d1581268..602f9b4fa6 100644
--- a/app/javascript/mastodon/components/avatar_overlay.tsx
+++ b/app/javascript/mastodon/components/avatar_overlay.tsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 import { useHovering } from '../../hooks/useHovering';
 import type { Account } from '../../types/resources';
 import { autoPlayGif } from '../initial_state';
diff --git a/app/javascript/mastodon/components/blurhash.tsx b/app/javascript/mastodon/components/blurhash.tsx
index 1550d0b7a5..8e2a8af23e 100644
--- a/app/javascript/mastodon/components/blurhash.tsx
+++ b/app/javascript/mastodon/components/blurhash.tsx
@@ -1,4 +1,4 @@
-import React, { useRef, useEffect } from 'react';
+import { memo, useRef, useEffect } from 'react';
 
 import { decode } from 'blurhash';
 
@@ -43,6 +43,6 @@ const Blurhash: React.FC<Props> = ({
   );
 };
 
-const MemoizedBlurhash = React.memo(Blurhash);
+const MemoizedBlurhash = memo(Blurhash);
 
 export { MemoizedBlurhash as Blurhash };
diff --git a/app/javascript/mastodon/components/button.jsx b/app/javascript/mastodon/components/button.jsx
index a05a75e893..1ad6cf4815 100644
--- a/app/javascript/mastodon/components/button.jsx
+++ b/app/javascript/mastodon/components/button.jsx
@@ -1,8 +1,8 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
 
-export default class Button extends React.PureComponent {
+export default class Button extends PureComponent {
 
   static propTypes = {
     text: PropTypes.node,
diff --git a/app/javascript/mastodon/components/check.tsx b/app/javascript/mastodon/components/check.tsx
index 73d65595ea..901f89fc5b 100644
--- a/app/javascript/mastodon/components/check.tsx
+++ b/app/javascript/mastodon/components/check.tsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 export const Check: React.FC = () => (
   <svg
     xmlns='http://www.w3.org/2000/svg'
diff --git a/app/javascript/mastodon/components/column.jsx b/app/javascript/mastodon/components/column.jsx
index c9ea5f7ac5..b57a08bd07 100644
--- a/app/javascript/mastodon/components/column.jsx
+++ b/app/javascript/mastodon/components/column.jsx
@@ -1,11 +1,11 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { supportsPassiveEvents } from 'detect-passive-events';
 import { scrollTop } from '../scroll';
 
 const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
 
-export default class Column extends React.PureComponent {
+export default class Column extends PureComponent {
 
   static propTypes = {
     children: PropTypes.node,
diff --git a/app/javascript/mastodon/components/column_back_button.jsx b/app/javascript/mastodon/components/column_back_button.jsx
index 19e2cb3637..bdd979ffaa 100644
--- a/app/javascript/mastodon/components/column_back_button.jsx
+++ b/app/javascript/mastodon/components/column_back_button.jsx
@@ -1,10 +1,10 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { FormattedMessage } from 'react-intl';
 import PropTypes from 'prop-types';
 import { Icon }  from 'mastodon/components/icon';
 import { createPortal } from 'react-dom';
 
-export default class ColumnBackButton extends React.PureComponent {
+export default class ColumnBackButton extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/components/column_back_button_slim.jsx b/app/javascript/mastodon/components/column_back_button_slim.jsx
index f2c8642eae..acdbce13ae 100644
--- a/app/javascript/mastodon/components/column_back_button_slim.jsx
+++ b/app/javascript/mastodon/components/column_back_button_slim.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { FormattedMessage } from 'react-intl';
 import ColumnBackButton from './column_back_button';
 import { Icon }  from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/components/column_header.jsx b/app/javascript/mastodon/components/column_header.jsx
index 794ea9738a..f66d6d06d2 100644
--- a/app/javascript/mastodon/components/column_header.jsx
+++ b/app/javascript/mastodon/components/column_header.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { createPortal } from 'react-dom';
 import classNames from 'classnames';
@@ -12,7 +12,7 @@ const messages = defineMessages({
   moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' },
 });
 
-class ColumnHeader extends React.PureComponent {
+class ColumnHeader extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/components/common_counter.jsx b/app/javascript/mastodon/components/common_counter.jsx
index 9964be5166..23e1f22638 100644
--- a/app/javascript/mastodon/components/common_counter.jsx
+++ b/app/javascript/mastodon/components/common_counter.jsx
@@ -1,5 +1,4 @@
 // @ts-check
-import React from 'react';
 import { FormattedMessage } from 'react-intl';
 
 /**
diff --git a/app/javascript/mastodon/components/dismissable_banner.jsx b/app/javascript/mastodon/components/dismissable_banner.jsx
index c433d95324..8e48497921 100644
--- a/app/javascript/mastodon/components/dismissable_banner.jsx
+++ b/app/javascript/mastodon/components/dismissable_banner.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { IconButton } from './icon_button';
 import PropTypes from 'prop-types';
 import { injectIntl, defineMessages } from 'react-intl';
@@ -8,7 +8,7 @@ const messages = defineMessages({
   dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' },
 });
 
-class DismissableBanner extends React.PureComponent {
+class DismissableBanner extends PureComponent {
 
   static propTypes = {
     id: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/components/domain.tsx b/app/javascript/mastodon/components/domain.tsx
index 9e8e04b65c..db18635be1 100644
--- a/app/javascript/mastodon/components/domain.tsx
+++ b/app/javascript/mastodon/components/domain.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import { useCallback } from 'react';
 
 import type { InjectedIntl } from 'react-intl';
 import { defineMessages, injectIntl } from 'react-intl';
diff --git a/app/javascript/mastodon/components/dropdown_menu.jsx b/app/javascript/mastodon/components/dropdown_menu.jsx
index 0336585f14..4a3c211c7b 100644
--- a/app/javascript/mastodon/components/dropdown_menu.jsx
+++ b/app/javascript/mastodon/components/dropdown_menu.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, cloneElement, Children, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { IconButton } from './icon_button';
@@ -10,7 +10,7 @@ import { CircularProgress } from 'mastodon/components/loading_indicator';
 const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
 let id = 0;
 
-class DropdownMenu extends React.PureComponent {
+class DropdownMenu extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
@@ -155,7 +155,7 @@ class DropdownMenu extends React.PureComponent {
 
 }
 
-export default class Dropdown extends React.PureComponent {
+export default class Dropdown extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
@@ -286,7 +286,7 @@ export default class Dropdown extends React.PureComponent {
 
     const open = this.state.id === openDropdownId;
 
-    const button = children ? React.cloneElement(React.Children.only(children), {
+    const button = children ? cloneElement(Children.only(children), {
       onClick: this.handleClick,
       onMouseDown: this.handleMouseDown,
       onKeyDown: this.handleButtonKeyDown,
@@ -306,7 +306,7 @@ export default class Dropdown extends React.PureComponent {
     );
 
     return (
-      <React.Fragment>
+      <Fragment>
         <span ref={this.setTargetRef}>
           {button}
         </span>
@@ -329,7 +329,7 @@ export default class Dropdown extends React.PureComponent {
             </div>
           )}
         </Overlay>
-      </React.Fragment>
+      </Fragment>
     );
   }
 
diff --git a/app/javascript/mastodon/components/edited_timestamp/index.jsx b/app/javascript/mastodon/components/edited_timestamp/index.jsx
index 745d8a4b6f..12ebfe0567 100644
--- a/app/javascript/mastodon/components/edited_timestamp/index.jsx
+++ b/app/javascript/mastodon/components/edited_timestamp/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { FormattedMessage, injectIntl } from 'react-intl';
 import { Icon }  from 'mastodon/components/icon';
@@ -16,7 +16,7 @@ const mapDispatchToProps = (dispatch, { statusId }) => ({
 
 });
 
-class EditedTimestamp extends React.PureComponent {
+class EditedTimestamp extends PureComponent {
 
   static propTypes = {
     statusId: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/components/error_boundary.jsx b/app/javascript/mastodon/components/error_boundary.jsx
index b711f1e461..43cce0679c 100644
--- a/app/javascript/mastodon/components/error_boundary.jsx
+++ b/app/javascript/mastodon/components/error_boundary.jsx
@@ -1,11 +1,11 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { FormattedMessage } from 'react-intl';
 import { version, source_url } from 'mastodon/initial_state';
 import StackTrace from 'stacktrace-js';
 import { Helmet } from 'react-helmet';
 
-export default class ErrorBoundary extends React.PureComponent {
+export default class ErrorBoundary extends PureComponent {
 
   static propTypes = {
     children: PropTypes.node,
diff --git a/app/javascript/mastodon/components/gifv.tsx b/app/javascript/mastodon/components/gifv.tsx
index c606a29048..ac148c5a21 100644
--- a/app/javascript/mastodon/components/gifv.tsx
+++ b/app/javascript/mastodon/components/gifv.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useState } from 'react';
+import { useCallback, useState } from 'react';
 
 interface Props {
   src: string;
diff --git a/app/javascript/mastodon/components/hashtag.jsx b/app/javascript/mastodon/components/hashtag.jsx
index 3efd679a52..0f1d3877c2 100644
--- a/app/javascript/mastodon/components/hashtag.jsx
+++ b/app/javascript/mastodon/components/hashtag.jsx
@@ -1,5 +1,5 @@
 // @ts-check
-import React from 'react';
+import { Component, Fragment } from 'react';
 import { Sparklines, SparklinesCurve } from 'react-sparklines';
 import { FormattedMessage } from 'react-intl';
 import PropTypes from 'prop-types';
@@ -9,7 +9,7 @@ import ShortNumber from 'mastodon/components/short_number';
 import { Skeleton } from 'mastodon/components/skeleton';
 import classNames from 'classnames';
 
-class SilentErrorBoundary extends React.Component {
+class SilentErrorBoundary extends Component {
 
   static propTypes = {
     children: PropTypes.node,
@@ -69,7 +69,7 @@ const Hashtag = ({ name, to, people, uses, history, className, description, with
   <div className={classNames('trends__item', className)}>
     <div className='trends__item__name'>
       <Link to={to}>
-        {name ? <React.Fragment>#<span>{name}</span></React.Fragment> : <Skeleton width={50} />}
+        {name ? <Fragment>#<span>{name}</span></Fragment> : <Skeleton width={50} />}
       </Link>
 
       {description ? (
diff --git a/app/javascript/mastodon/components/icon.tsx b/app/javascript/mastodon/components/icon.tsx
index 6bd15da6ac..3d091c7059 100644
--- a/app/javascript/mastodon/components/icon.tsx
+++ b/app/javascript/mastodon/components/icon.tsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 import classNames from 'classnames';
 
 interface Props extends React.HTMLAttributes<HTMLImageElement> {
diff --git a/app/javascript/mastodon/components/icon_button.tsx b/app/javascript/mastodon/components/icon_button.tsx
index c995ed0ebe..9dbee2cc24 100644
--- a/app/javascript/mastodon/components/icon_button.tsx
+++ b/app/javascript/mastodon/components/icon_button.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 
 import classNames from 'classnames';
 
@@ -32,7 +32,7 @@ interface States {
   activate: boolean;
   deactivate: boolean;
 }
-export class IconButton extends React.PureComponent<Props, States> {
+export class IconButton extends PureComponent<Props, States> {
   static defaultProps = {
     size: 18,
     active: false,
@@ -127,14 +127,14 @@ export class IconButton extends React.PureComponent<Props, States> {
     }
 
     let contents = (
-      <React.Fragment>
+      <>
         <Icon id={icon} fixedWidth aria-hidden='true' />{' '}
         {typeof counter !== 'undefined' && (
           <span className='icon-button__counter'>
             <AnimatedNumber value={counter} obfuscate={obfuscateCount} />
           </span>
         )}
-      </React.Fragment>
+      </>
     );
 
     if (href != null) {
diff --git a/app/javascript/mastodon/components/icon_with_badge.tsx b/app/javascript/mastodon/components/icon_with_badge.tsx
index e427b7172b..8898f41329 100644
--- a/app/javascript/mastodon/components/icon_with_badge.tsx
+++ b/app/javascript/mastodon/components/icon_with_badge.tsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 import { Icon } from './icon';
 
 const formatNumber = (num: number): number | string => (num > 40 ? '40+' : num);
diff --git a/app/javascript/mastodon/components/inline_account.jsx b/app/javascript/mastodon/components/inline_account.jsx
index ca11f8b1bc..4366af3c7c 100644
--- a/app/javascript/mastodon/components/inline_account.jsx
+++ b/app/javascript/mastodon/components/inline_account.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { connect } from 'react-redux';
 import { makeGetAccount } from 'mastodon/selectors';
@@ -14,7 +14,7 @@ const makeMapStateToProps = () => {
   return mapStateToProps;
 };
 
-class InlineAccount extends React.PureComponent {
+class InlineAccount extends PureComponent {
 
   static propTypes = {
     account: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/components/intersection_observer_article.jsx b/app/javascript/mastodon/components/intersection_observer_article.jsx
index 77957a21da..faba01b80e 100644
--- a/app/javascript/mastodon/components/intersection_observer_article.jsx
+++ b/app/javascript/mastodon/components/intersection_observer_article.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { cloneElement, Component } from 'react';
 import PropTypes from 'prop-types';
 import scheduleIdleTask from '../features/ui/util/schedule_idle_task';
 import getRectFromEntry from '../features/ui/util/get_rect_from_entry';
@@ -6,7 +6,7 @@ import getRectFromEntry from '../features/ui/util/get_rect_from_entry';
 // Diff these props in the "unrendered" state
 const updateOnPropsForUnrendered = ['id', 'index', 'listLength', 'cachedHeight'];
 
-export default class IntersectionObserverArticle extends React.Component {
+export default class IntersectionObserverArticle extends Component {
 
   static propTypes = {
     intersectionObserverWrapper: PropTypes.object.isRequired,
@@ -115,14 +115,14 @@ export default class IntersectionObserverArticle extends React.Component {
           data-id={id}
           tabIndex={0}
         >
-          {children && React.cloneElement(children, { hidden: true })}
+          {children && cloneElement(children, { hidden: true })}
         </article>
       );
     }
 
     return (
       <article ref={this.handleRef} aria-posinset={index + 1} aria-setsize={listLength} data-id={id} tabIndex={0}>
-        {children && React.cloneElement(children, { hidden: false })}
+        {children && cloneElement(children, { hidden: false })}
       </article>
     );
   }
diff --git a/app/javascript/mastodon/components/load_gap.jsx b/app/javascript/mastodon/components/load_gap.jsx
index 2637bdbbc4..e4da2748a2 100644
--- a/app/javascript/mastodon/components/load_gap.jsx
+++ b/app/javascript/mastodon/components/load_gap.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { injectIntl, defineMessages } from 'react-intl';
 import { Icon }  from 'mastodon/components/icon';
@@ -7,7 +7,7 @@ const messages = defineMessages({
   load_more: { id: 'status.load_more', defaultMessage: 'Load more' },
 });
 
-class LoadGap extends React.PureComponent {
+class LoadGap extends PureComponent {
 
   static propTypes = {
     disabled: PropTypes.bool,
diff --git a/app/javascript/mastodon/components/load_more.jsx b/app/javascript/mastodon/components/load_more.jsx
index 150525214b..b077b89282 100644
--- a/app/javascript/mastodon/components/load_more.jsx
+++ b/app/javascript/mastodon/components/load_more.jsx
@@ -1,8 +1,8 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { FormattedMessage } from 'react-intl';
 import PropTypes from 'prop-types';
 
-export default class LoadMore extends React.PureComponent {
+export default class LoadMore extends PureComponent {
 
   static propTypes = {
     onClick: PropTypes.func,
diff --git a/app/javascript/mastodon/components/load_pending.jsx b/app/javascript/mastodon/components/load_pending.jsx
index a75259146a..d05e6b1dc9 100644
--- a/app/javascript/mastodon/components/load_pending.jsx
+++ b/app/javascript/mastodon/components/load_pending.jsx
@@ -1,8 +1,8 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { FormattedMessage } from 'react-intl';
 import PropTypes from 'prop-types';
 
-export default class LoadPending extends React.PureComponent {
+export default class LoadPending extends PureComponent {
 
   static propTypes = {
     onClick: PropTypes.func,
diff --git a/app/javascript/mastodon/components/loading_indicator.jsx b/app/javascript/mastodon/components/loading_indicator.jsx
index 33c59d94c0..c3f7a4e9ef 100644
--- a/app/javascript/mastodon/components/loading_indicator.jsx
+++ b/app/javascript/mastodon/components/loading_indicator.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 
 export const CircularProgress = ({ size, strokeWidth }) => {
diff --git a/app/javascript/mastodon/components/logo.tsx b/app/javascript/mastodon/components/logo.tsx
index 6594ef1fd4..928aa29a7c 100644
--- a/app/javascript/mastodon/components/logo.tsx
+++ b/app/javascript/mastodon/components/logo.tsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 import logo from 'mastodon/../images/logo.svg';
 
 export const WordmarkLogo: React.FC = () => (
diff --git a/app/javascript/mastodon/components/media_attachments.jsx b/app/javascript/mastodon/components/media_attachments.jsx
index 0e25e59734..055be5d287 100644
--- a/app/javascript/mastodon/components/media_attachments.jsx
+++ b/app/javascript/mastodon/components/media_attachments.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx
index 6653f8632d..90345c867b 100644
--- a/app/javascript/mastodon/components/media_gallery.jsx
+++ b/app/javascript/mastodon/components/media_gallery.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import { is } from 'immutable';
@@ -13,7 +13,7 @@ const messages = defineMessages({
   toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: '{number, plural, one {Hide image} other {Hide images}}' },
 });
 
-class Item extends React.PureComponent {
+class Item extends PureComponent {
 
   static propTypes = {
     attachment: ImmutablePropTypes.map.isRequired,
@@ -196,7 +196,7 @@ class Item extends React.PureComponent {
 
 }
 
-class MediaGallery extends React.PureComponent {
+class MediaGallery extends PureComponent {
 
   static propTypes = {
     sensitive: PropTypes.bool,
diff --git a/app/javascript/mastodon/components/modal_root.jsx b/app/javascript/mastodon/components/modal_root.jsx
index 7671d2725d..b735f7734e 100644
--- a/app/javascript/mastodon/components/modal_root.jsx
+++ b/app/javascript/mastodon/components/modal_root.jsx
@@ -1,10 +1,10 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import 'wicg-inert';
 import { createBrowserHistory } from 'history';
 import { multiply } from 'color-blend';
 
-export default class ModalRoot extends React.PureComponent {
+export default class ModalRoot extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/components/navigation_portal.jsx b/app/javascript/mastodon/components/navigation_portal.jsx
index a100dc04a6..40c47c0218 100644
--- a/app/javascript/mastodon/components/navigation_portal.jsx
+++ b/app/javascript/mastodon/components/navigation_portal.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { Switch, Route, withRouter } from 'react-router-dom';
 import { showTrends } from 'mastodon/initial_state';
 import Trends from 'mastodon/features/getting_started/containers/trends_container';
@@ -15,7 +15,7 @@ const DefaultNavigation = () => (
   </>
 );
 
-class NavigationPortal extends React.PureComponent {
+class NavigationPortal extends PureComponent {
 
   render () {
     return (
diff --git a/app/javascript/mastodon/components/not_signed_in_indicator.tsx b/app/javascript/mastodon/components/not_signed_in_indicator.tsx
index ce94c5d873..015f74dcae 100644
--- a/app/javascript/mastodon/components/not_signed_in_indicator.tsx
+++ b/app/javascript/mastodon/components/not_signed_in_indicator.tsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 import { FormattedMessage } from 'react-intl';
 
 export const NotSignedInIndicator: React.FC = () => (
diff --git a/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx b/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
index 4763a28d10..e44aafd092 100644
--- a/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
+++ b/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
@@ -1,11 +1,11 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { Icon }  from 'mastodon/components/icon';
 import { removePictureInPicture } from 'mastodon/actions/picture_in_picture';
 import { connect } from 'react-redux';
 import { FormattedMessage } from 'react-intl';
 
-class PictureInPicturePlaceholder extends React.PureComponent {
+class PictureInPicturePlaceholder extends PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/components/poll.jsx b/app/javascript/mastodon/components/poll.jsx
index 0ccdf472eb..506b9d3f7e 100644
--- a/app/javascript/mastodon/components/poll.jsx
+++ b/app/javascript/mastodon/components/poll.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/components/radio_button.tsx b/app/javascript/mastodon/components/radio_button.tsx
index 67acb09f42..d0a565b9e6 100644
--- a/app/javascript/mastodon/components/radio_button.tsx
+++ b/app/javascript/mastodon/components/radio_button.tsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 import classNames from 'classnames';
 
 interface Props {
diff --git a/app/javascript/mastodon/components/regeneration_indicator.jsx b/app/javascript/mastodon/components/regeneration_indicator.jsx
index 52696a4a72..dbefc7a9b9 100644
--- a/app/javascript/mastodon/components/regeneration_indicator.jsx
+++ b/app/javascript/mastodon/components/regeneration_indicator.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { FormattedMessage } from 'react-intl';
 import illustration from 'mastodon/../images/elephant_ui_working.svg';
 
diff --git a/app/javascript/mastodon/components/relative_timestamp.tsx b/app/javascript/mastodon/components/relative_timestamp.tsx
index e0e0d4bb53..aaa424dca6 100644
--- a/app/javascript/mastodon/components/relative_timestamp.tsx
+++ b/app/javascript/mastodon/components/relative_timestamp.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { Component } from 'react';
 
 import type { InjectedIntl } from 'react-intl';
 import { injectIntl, defineMessages } from 'react-intl';
@@ -199,7 +199,7 @@ interface Props {
 interface States {
   now: number;
 }
-class RelativeTimestamp extends React.Component<Props, States> {
+class RelativeTimestamp extends Component<Props, States> {
   state = {
     now: this.props.intl.now(),
   };
diff --git a/app/javascript/mastodon/components/scrollable_list.jsx b/app/javascript/mastodon/components/scrollable_list.jsx
index 9b9e1e7449..6fed295da4 100644
--- a/app/javascript/mastodon/components/scrollable_list.jsx
+++ b/app/javascript/mastodon/components/scrollable_list.jsx
@@ -1,4 +1,4 @@
-import React, { PureComponent } from 'react';
+import { Children, cloneElement, PureComponent } from 'react';
 import ScrollContainer from 'mastodon/containers/scroll_container';
 import PropTypes from 'prop-types';
 import IntersectionObserverArticleContainer from '../containers/intersection_observer_article_container';
@@ -184,8 +184,8 @@ class ScrollableList extends PureComponent {
   };
 
   getSnapshotBeforeUpdate (prevProps) {
-    const someItemInserted = React.Children.count(prevProps.children) > 0 &&
-      React.Children.count(prevProps.children) < React.Children.count(this.props.children) &&
+    const someItemInserted = Children.count(prevProps.children) > 0 &&
+      Children.count(prevProps.children) < Children.count(this.props.children) &&
       this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props);
     const pendingChanged = (prevProps.numPending > 0) !== (this.props.numPending > 0);
 
@@ -293,7 +293,7 @@ class ScrollableList extends PureComponent {
   render () {
     const { children, scrollKey, trackScroll, showLoading, isLoading, hasMore, numPending, prepend, alwaysPrepend, append, emptyMessage, onLoadMore } = this.props;
     const { fullscreen } = this.state;
-    const childrenCount = React.Children.count(children);
+    const childrenCount = Children.count(children);
 
     const loadMore     = (hasMore && onLoadMore) ? <LoadMore visible={!isLoading} onClick={this.handleLoadMore} /> : null;
     const loadPending  = (numPending > 0) ? <LoadPending count={numPending} onClick={this.handleLoadPending} /> : null;
@@ -319,7 +319,7 @@ class ScrollableList extends PureComponent {
 
             {loadPending}
 
-            {React.Children.map(this.props.children, (child, index) => (
+            {Children.map(this.props.children, (child, index) => (
               <IntersectionObserverArticleContainer
                 key={child.key}
                 id={child.key}
@@ -328,7 +328,7 @@ class ScrollableList extends PureComponent {
                 intersectionObserverWrapper={this.intersectionObserverWrapper}
                 saveHeightKey={trackScroll ? `${this.context.router.route.location.key}:${scrollKey}` : null}
               >
-                {React.cloneElement(child, {
+                {cloneElement(child, {
                   getScrollPosition: this.getScrollPosition,
                   updateScrollBottom: this.updateScrollBottom,
                   cachedMediaWidth: this.state.cachedMediaWidth,
diff --git a/app/javascript/mastodon/components/server_banner.jsx b/app/javascript/mastodon/components/server_banner.jsx
index 6c3abd5b6f..9d41700a18 100644
--- a/app/javascript/mastodon/components/server_banner.jsx
+++ b/app/javascript/mastodon/components/server_banner.jsx
@@ -1,5 +1,5 @@
 import PropTypes from 'prop-types';
-import React from 'react';
+import { PureComponent } from 'react';
 import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
 import { connect } from 'react-redux';
 import { fetchServer } from 'mastodon/actions/server';
@@ -18,7 +18,7 @@ const mapStateToProps = state => ({
   server: state.getIn(['server', 'server']),
 });
 
-class ServerBanner extends React.PureComponent {
+class ServerBanner extends PureComponent {
 
   static propTypes = {
     server: PropTypes.object,
diff --git a/app/javascript/mastodon/components/server_hero_image.tsx b/app/javascript/mastodon/components/server_hero_image.tsx
index 973d1d1b37..68b7f03df3 100644
--- a/app/javascript/mastodon/components/server_hero_image.tsx
+++ b/app/javascript/mastodon/components/server_hero_image.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useState } from 'react';
+import { useCallback, useState } from 'react';
 
 import classNames from 'classnames';
 
diff --git a/app/javascript/mastodon/components/short_number.jsx b/app/javascript/mastodon/components/short_number.jsx
index 0c40941c0d..550ed7d0ac 100644
--- a/app/javascript/mastodon/components/short_number.jsx
+++ b/app/javascript/mastodon/components/short_number.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { memo } from 'react';
 import PropTypes from 'prop-types';
 import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers';
 import { FormattedMessage, FormattedNumber } from 'react-intl';
@@ -109,4 +109,4 @@ ShortNumberCounter.propTypes = {
   value: PropTypes.arrayOf(PropTypes.number),
 };
 
-export default React.memo(ShortNumber);
+export default memo(ShortNumber);
diff --git a/app/javascript/mastodon/components/skeleton.tsx b/app/javascript/mastodon/components/skeleton.tsx
index 8d43e6827d..d6f1aed723 100644
--- a/app/javascript/mastodon/components/skeleton.tsx
+++ b/app/javascript/mastodon/components/skeleton.tsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 interface Props {
   width?: number | string;
   height?: number | string;
diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx
index 070ec4672a..536ac1dd27 100644
--- a/app/javascript/mastodon/components/status.jsx
+++ b/app/javascript/mastodon/components/status.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import { Avatar } from './avatar';
diff --git a/app/javascript/mastodon/components/status_action_bar.jsx b/app/javascript/mastodon/components/status_action_bar.jsx
index aee9cc19e8..2e83597da8 100644
--- a/app/javascript/mastodon/components/status_action_bar.jsx
+++ b/app/javascript/mastodon/components/status_action_bar.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx
index cece3ffc25..ffaaae28ea 100644
--- a/app/javascript/mastodon/components/status_content.jsx
+++ b/app/javascript/mastodon/components/status_content.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import { FormattedMessage, injectIntl } from 'react-intl';
@@ -11,7 +11,7 @@ import { autoPlayGif, languages as preloadedLanguages } from 'mastodon/initial_s
 
 const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
 
-class TranslateButton extends React.PureComponent {
+class TranslateButton extends PureComponent {
 
   static propTypes = {
     translation: ImmutablePropTypes.map,
@@ -52,7 +52,7 @@ const mapStateToProps = state => ({
   languages: state.getIn(['server', 'translationLanguages', 'items']),
 });
 
-class StatusContent extends React.PureComponent {
+class StatusContent extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/components/status_list.jsx b/app/javascript/mastodon/components/status_list.jsx
index 34b7732787..cd646be6ed 100644
--- a/app/javascript/mastodon/components/status_list.jsx
+++ b/app/javascript/mastodon/components/status_list.jsx
@@ -1,5 +1,4 @@
 import { debounce } from 'lodash';
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import StatusContainer from '../containers/status_container';
diff --git a/app/javascript/mastodon/components/timeline_hint.tsx b/app/javascript/mastodon/components/timeline_hint.tsx
index 712b4c293b..bf2a2d8bba 100644
--- a/app/javascript/mastodon/components/timeline_hint.tsx
+++ b/app/javascript/mastodon/components/timeline_hint.tsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 import { FormattedMessage } from 'react-intl';
 
 interface Props {
diff --git a/app/javascript/mastodon/components/verified_badge.tsx b/app/javascript/mastodon/components/verified_badge.tsx
index 4c5de31203..6b421ba42c 100644
--- a/app/javascript/mastodon/components/verified_badge.tsx
+++ b/app/javascript/mastodon/components/verified_badge.tsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 import { Icon } from './icon';
 
 interface Props {
diff --git a/app/javascript/mastodon/containers/account_container.jsx b/app/javascript/mastodon/containers/account_container.jsx
index 5a5136dd18..f3d3e039c7 100644
--- a/app/javascript/mastodon/containers/account_container.jsx
+++ b/app/javascript/mastodon/containers/account_container.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import { makeGetAccount } from '../selectors';
diff --git a/app/javascript/mastodon/containers/admin_component.jsx b/app/javascript/mastodon/containers/admin_component.jsx
index 816b44bd17..188485d40b 100644
--- a/app/javascript/mastodon/containers/admin_component.jsx
+++ b/app/javascript/mastodon/containers/admin_component.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { IntlProvider, addLocaleData } from 'react-intl';
 import { getLocale } from '../locales';
@@ -6,7 +6,7 @@ import { getLocale } from '../locales';
 const { localeData, messages } = getLocale();
 addLocaleData(localeData);
 
-export default class AdminComponent extends React.PureComponent {
+export default class AdminComponent extends PureComponent {
 
   static propTypes = {
     locale: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/containers/compose_container.jsx b/app/javascript/mastodon/containers/compose_container.jsx
index 9213c5614e..289369f07a 100644
--- a/app/javascript/mastodon/containers/compose_container.jsx
+++ b/app/javascript/mastodon/containers/compose_container.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { Provider } from 'react-redux';
 import PropTypes from 'prop-types';
 import { store } from '../store';
@@ -18,7 +18,7 @@ if (initialState) {
 
 store.dispatch(fetchCustomEmojis());
 
-export default class TimelineContainer extends React.PureComponent {
+export default class TimelineContainer extends PureComponent {
 
   static propTypes = {
     locale: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/containers/domain_container.jsx b/app/javascript/mastodon/containers/domain_container.jsx
index 419d5d29f5..bc2a448494 100644
--- a/app/javascript/mastodon/containers/domain_container.jsx
+++ b/app/javascript/mastodon/containers/domain_container.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { blockDomain, unblockDomain } from '../actions/domain_blocks';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
diff --git a/app/javascript/mastodon/containers/mastodon.jsx b/app/javascript/mastodon/containers/mastodon.jsx
index 9c6c9e5920..319425e3fc 100644
--- a/app/javascript/mastodon/containers/mastodon.jsx
+++ b/app/javascript/mastodon/containers/mastodon.jsx
@@ -1,5 +1,5 @@
 import PropTypes from 'prop-types';
-import React from 'react';
+import { PureComponent } from 'react';
 import { Helmet } from 'react-helmet';
 import { IntlProvider, addLocaleData } from 'react-intl';
 import { Provider as ReduxProvider } from 'react-redux';
@@ -34,7 +34,7 @@ const createIdentityContext = state => ({
   permissions: state.role ? state.role.permissions : 0,
 });
 
-export default class Mastodon extends React.PureComponent {
+export default class Mastodon extends PureComponent {
 
   static propTypes = {
     locale: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/containers/media_container.jsx b/app/javascript/mastodon/containers/media_container.jsx
index 1b6caaba8c..4d1689c235 100644
--- a/app/javascript/mastodon/containers/media_container.jsx
+++ b/app/javascript/mastodon/containers/media_container.jsx
@@ -1,4 +1,4 @@
-import React, { PureComponent, Fragment } from 'react';
+import { PureComponent, Fragment } from 'react';
 import { createPortal } from 'react-dom';
 import PropTypes from 'prop-types';
 import { IntlProvider, addLocaleData } from 'react-intl';
diff --git a/app/javascript/mastodon/containers/status_container.jsx b/app/javascript/mastodon/containers/status_container.jsx
index b54501f009..45b384028d 100644
--- a/app/javascript/mastodon/containers/status_container.jsx
+++ b/app/javascript/mastodon/containers/status_container.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import Status from '../components/status';
 import { makeGetStatus, makeGetPictureInPicture } from '../selectors';
diff --git a/app/javascript/mastodon/features/about/index.jsx b/app/javascript/mastodon/features/about/index.jsx
index 61a9180a10..5697eb25bb 100644
--- a/app/javascript/mastodon/features/about/index.jsx
+++ b/app/javascript/mastodon/features/about/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import { connect } from 'react-redux';
@@ -41,7 +41,7 @@ const mapStateToProps = state => ({
   domainBlocks: state.getIn(['server', 'domainBlocks']),
 });
 
-class Section extends React.PureComponent {
+class Section extends PureComponent {
 
   static propTypes = {
     title: PropTypes.string,
@@ -80,7 +80,7 @@ class Section extends React.PureComponent {
 
 }
 
-class About extends React.PureComponent {
+class About extends PureComponent {
 
   static propTypes = {
     server: ImmutablePropTypes.map,
diff --git a/app/javascript/mastodon/features/account/components/account_note.jsx b/app/javascript/mastodon/features/account/components/account_note.jsx
index 9a81b0aee2..02746b4f02 100644
--- a/app/javascript/mastodon/features/account/components/account_note.jsx
+++ b/app/javascript/mastodon/features/account/components/account_note.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
@@ -10,7 +10,7 @@ const messages = defineMessages({
   placeholder: { id: 'account_note.placeholder', defaultMessage: 'Click to add a note' },
 });
 
-class InlineAlert extends React.PureComponent {
+class InlineAlert extends PureComponent {
 
   static propTypes = {
     show: PropTypes.bool,
diff --git a/app/javascript/mastodon/features/account/components/featured_tags.jsx b/app/javascript/mastodon/features/account/components/featured_tags.jsx
index 52aa232caf..ad903e2151 100644
--- a/app/javascript/mastodon/features/account/components/featured_tags.jsx
+++ b/app/javascript/mastodon/features/account/components/featured_tags.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/account/components/follow_request_note.jsx b/app/javascript/mastodon/features/account/components/follow_request_note.jsx
index 7972515af5..beaed10ce9 100644
--- a/app/javascript/mastodon/features/account/components/follow_request_note.jsx
+++ b/app/javascript/mastodon/features/account/components/follow_request_note.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { FormattedMessage } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/account/components/header.jsx b/app/javascript/mastodon/features/account/components/header.jsx
index bb0982b5e4..2784441c9c 100644
--- a/app/javascript/mastodon/features/account/components/header.jsx
+++ b/app/javascript/mastodon/features/account/components/header.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { Fragment } from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
@@ -399,10 +399,10 @@ class Header extends ImmutablePureComponent {
             {!suspended && (
               <div className='account__header__tabs__buttons'>
                 {!hidden && (
-                  <React.Fragment>
+                  <Fragment>
                     {actionBtn}
                     {bellBtn}
-                  </React.Fragment>
+                  </Fragment>
                 )}
 
                 <DropdownMenuContainer disabled={menu.length === 0} items={menu} icon='ellipsis-v' size={24} direction='right' />
diff --git a/app/javascript/mastodon/features/account/navigation.jsx b/app/javascript/mastodon/features/account/navigation.jsx
index 07dc3757cc..e1558addaf 100644
--- a/app/javascript/mastodon/features/account/navigation.jsx
+++ b/app/javascript/mastodon/features/account/navigation.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { connect } from 'react-redux';
 import FeaturedTags from 'mastodon/features/account/containers/featured_tags_container';
@@ -19,7 +19,7 @@ const mapStateToProps = (state, { match: { params: { acct } } }) => {
   };
 };
 
-class AccountNavigation extends React.PureComponent {
+class AccountNavigation extends PureComponent {
 
   static propTypes = {
     match: PropTypes.shape({
diff --git a/app/javascript/mastodon/features/account_gallery/components/media_item.jsx b/app/javascript/mastodon/features/account_gallery/components/media_item.jsx
index 9e9b9e6e16..ffbbe661e1 100644
--- a/app/javascript/mastodon/features/account_gallery/components/media_item.jsx
+++ b/app/javascript/mastodon/features/account_gallery/components/media_item.jsx
@@ -3,7 +3,6 @@ import classNames from 'classnames';
 import { Icon }  from 'mastodon/components/icon';
 import { autoPlayGif, displayMedia, useBlurhash } from 'mastodon/initial_state';
 import PropTypes from 'prop-types';
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 
diff --git a/app/javascript/mastodon/features/account_gallery/index.jsx b/app/javascript/mastodon/features/account_gallery/index.jsx
index 8c44fa346f..1d9954b668 100644
--- a/app/javascript/mastodon/features/account_gallery/index.jsx
+++ b/app/javascript/mastodon/features/account_gallery/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/account_timeline/components/header.jsx b/app/javascript/mastodon/features/account_timeline/components/header.jsx
index e64deaefa6..611efcc5cc 100644
--- a/app/javascript/mastodon/features/account_timeline/components/header.jsx
+++ b/app/javascript/mastodon/features/account_timeline/components/header.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import InnerHeader from '../../account/components/header';
diff --git a/app/javascript/mastodon/features/account_timeline/components/limited_account_hint.jsx b/app/javascript/mastodon/features/account_timeline/components/limited_account_hint.jsx
index e6a1114706..ebe96d7db8 100644
--- a/app/javascript/mastodon/features/account_timeline/components/limited_account_hint.jsx
+++ b/app/javascript/mastodon/features/account_timeline/components/limited_account_hint.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { connect } from 'react-redux';
 import { revealAccount } from 'mastodon/actions/accounts';
@@ -14,7 +14,7 @@ const mapDispatchToProps = (dispatch, { accountId }) => ({
 
 });
 
-class LimitedAccountHint extends React.PureComponent {
+class LimitedAccountHint extends PureComponent {
 
   static propTypes = {
     accountId: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/account_timeline/components/memorial_note.jsx b/app/javascript/mastodon/features/account_timeline/components/memorial_note.jsx
index fed95ac2ab..a04808f1ca 100644
--- a/app/javascript/mastodon/features/account_timeline/components/memorial_note.jsx
+++ b/app/javascript/mastodon/features/account_timeline/components/memorial_note.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { FormattedMessage } from 'react-intl';
 
 const MemorialNote = () => (
diff --git a/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx b/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx
index 29861612c3..7c8da1c2f4 100644
--- a/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx
+++ b/app/javascript/mastodon/features/account_timeline/components/moved_note.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { FormattedMessage } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx
index 419a9fa566..15648612ce 100644
--- a/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx
+++ b/app/javascript/mastodon/features/account_timeline/containers/header_container.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { makeGetAccount, getAccountHidden } from '../../../selectors';
 import Header from '../components/header';
diff --git a/app/javascript/mastodon/features/account_timeline/index.jsx b/app/javascript/mastodon/features/account_timeline/index.jsx
index ce9485216e..2576d48cf2 100644
--- a/app/javascript/mastodon/features/account_timeline/index.jsx
+++ b/app/javascript/mastodon/features/account_timeline/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/audio/index.jsx b/app/javascript/mastodon/features/audio/index.jsx
index 5ed02d9378..d81813cf0d 100644
--- a/app/javascript/mastodon/features/audio/index.jsx
+++ b/app/javascript/mastodon/features/audio/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
 import { formatTime, getPointerPosition, fileNameFromURL } from 'mastodon/features/video';
@@ -22,7 +22,7 @@ const messages = defineMessages({
 const TICK_SIZE = 10;
 const PADDING   = 180;
 
-class Audio extends React.PureComponent {
+class Audio extends PureComponent {
 
   static propTypes = {
     src: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/blocks/index.jsx b/app/javascript/mastodon/features/blocks/index.jsx
index da28f12d79..088545bde9 100644
--- a/app/javascript/mastodon/features/blocks/index.jsx
+++ b/app/javascript/mastodon/features/blocks/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/bookmarked_statuses/index.jsx b/app/javascript/mastodon/features/bookmarked_statuses/index.jsx
index 1ffe7e768d..7a3ca39b74 100644
--- a/app/javascript/mastodon/features/bookmarked_statuses/index.jsx
+++ b/app/javascript/mastodon/features/bookmarked_statuses/index.jsx
@@ -1,6 +1,5 @@
 import { debounce } from 'lodash';
 import PropTypes from 'prop-types';
-import React from 'react';
 import { Helmet } from 'react-helmet';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import ImmutablePropTypes from 'react-immutable-proptypes';
diff --git a/app/javascript/mastodon/features/closed_registrations_modal/index.jsx b/app/javascript/mastodon/features/closed_registrations_modal/index.jsx
index 40df804f2d..9ff167ecfc 100644
--- a/app/javascript/mastodon/features/closed_registrations_modal/index.jsx
+++ b/app/javascript/mastodon/features/closed_registrations_modal/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { FormattedMessage } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/community_timeline/components/column_settings.jsx b/app/javascript/mastodon/features/community_timeline/components/column_settings.jsx
index d6181919ab..c71f301cb0 100644
--- a/app/javascript/mastodon/features/community_timeline/components/column_settings.jsx
+++ b/app/javascript/mastodon/features/community_timeline/components/column_settings.jsx
@@ -1,10 +1,10 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { injectIntl, FormattedMessage } from 'react-intl';
 import SettingToggle from '../../notifications/components/setting_toggle';
 
-class ColumnSettings extends React.PureComponent {
+class ColumnSettings extends PureComponent {
 
   static propTypes = {
     settings: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/community_timeline/index.jsx b/app/javascript/mastodon/features/community_timeline/index.jsx
index e41d11bb5c..bdcefe73d0 100644
--- a/app/javascript/mastodon/features/community_timeline/index.jsx
+++ b/app/javascript/mastodon/features/community_timeline/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import PropTypes from 'prop-types';
@@ -30,7 +30,7 @@ const mapStateToProps = (state, { columnId }) => {
   };
 };
 
-class CommunityTimeline extends React.PureComponent {
+class CommunityTimeline extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/compose/components/action_bar.jsx b/app/javascript/mastodon/features/compose/components/action_bar.jsx
index 13760582ec..3382a5ce44 100644
--- a/app/javascript/mastodon/features/compose/components/action_bar.jsx
+++ b/app/javascript/mastodon/features/compose/components/action_bar.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
@@ -20,7 +20,7 @@ const messages = defineMessages({
   bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' },
 });
 
-class ActionBar extends React.PureComponent {
+class ActionBar extends PureComponent {
 
   static propTypes = {
     account: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx b/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx
index a635657d9f..2231beb767 100644
--- a/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx
+++ b/app/javascript/mastodon/features/compose/components/autosuggest_account.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { Avatar } from '../../../components/avatar';
 import { DisplayName } from '../../../components/display_name';
 import ImmutablePropTypes from 'react-immutable-proptypes';
diff --git a/app/javascript/mastodon/features/compose/components/character_counter.jsx b/app/javascript/mastodon/features/compose/components/character_counter.jsx
index 0ecfc9141d..15fc77bdcd 100644
--- a/app/javascript/mastodon/features/compose/components/character_counter.jsx
+++ b/app/javascript/mastodon/features/compose/components/character_counter.jsx
@@ -1,8 +1,8 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { length } from 'stringz';
 
-export default class CharacterCounter extends React.PureComponent {
+export default class CharacterCounter extends PureComponent {
 
   static propTypes = {
     text: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/compose/components/compose_form.jsx b/app/javascript/mastodon/features/compose/components/compose_form.jsx
index 3f42cb885e..7ac2526f20 100644
--- a/app/javascript/mastodon/features/compose/components/compose_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/compose_form.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import CharacterCounter from './character_counter';
 import Button from '../../../components/button';
 import ImmutablePropTypes from 'react-immutable-proptypes';
diff --git a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.jsx b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.jsx
index c12d56e4a9..0bef6ccdb0 100644
--- a/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.jsx
+++ b/app/javascript/mastodon/features/compose/components/emoji_picker_dropdown.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components';
@@ -47,7 +47,7 @@ const notFoundFn = () => (
   </div>
 );
 
-class ModifierPickerMenu extends React.PureComponent {
+class ModifierPickerMenu extends PureComponent {
 
   static propTypes = {
     active: PropTypes.bool,
@@ -108,7 +108,7 @@ class ModifierPickerMenu extends React.PureComponent {
 
 }
 
-class ModifierPicker extends React.PureComponent {
+class ModifierPicker extends PureComponent {
 
   static propTypes = {
     active: PropTypes.bool,
@@ -144,7 +144,7 @@ class ModifierPicker extends React.PureComponent {
 
 }
 
-class EmojiPickerMenuImpl extends React.PureComponent {
+class EmojiPickerMenuImpl extends PureComponent {
 
   static propTypes = {
     custom_emojis: ImmutablePropTypes.list,
@@ -306,7 +306,7 @@ class EmojiPickerMenuImpl extends React.PureComponent {
 
 const EmojiPickerMenu = injectIntl(EmojiPickerMenuImpl);
 
-class EmojiPickerDropdown extends React.PureComponent {
+class EmojiPickerDropdown extends PureComponent {
 
   static propTypes = {
     custom_emojis: ImmutablePropTypes.list,
diff --git a/app/javascript/mastodon/features/compose/components/language_dropdown.jsx b/app/javascript/mastodon/features/compose/components/language_dropdown.jsx
index 731d7b38de..639832c452 100644
--- a/app/javascript/mastodon/features/compose/components/language_dropdown.jsx
+++ b/app/javascript/mastodon/features/compose/components/language_dropdown.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { injectIntl, defineMessages } from 'react-intl';
 import TextIconButton from './text_icon_button';
@@ -17,7 +17,7 @@ const messages = defineMessages({
 
 const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
 
-class LanguageDropdownMenu extends React.PureComponent {
+class LanguageDropdownMenu extends PureComponent {
 
   static propTypes = {
     value: PropTypes.string.isRequired,
@@ -238,7 +238,7 @@ class LanguageDropdownMenu extends React.PureComponent {
 
 }
 
-class LanguageDropdown extends React.PureComponent {
+class LanguageDropdown extends PureComponent {
 
   static propTypes = {
     value: PropTypes.string,
diff --git a/app/javascript/mastodon/features/compose/components/navigation_bar.jsx b/app/javascript/mastodon/features/compose/components/navigation_bar.jsx
index b5a7b6bda2..3a2e535948 100644
--- a/app/javascript/mastodon/features/compose/components/navigation_bar.jsx
+++ b/app/javascript/mastodon/features/compose/components/navigation_bar.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ActionBar from './action_bar';
diff --git a/app/javascript/mastodon/features/compose/components/poll_button.jsx b/app/javascript/mastodon/features/compose/components/poll_button.jsx
index 5d90564bd1..9c9a94629e 100644
--- a/app/javascript/mastodon/features/compose/components/poll_button.jsx
+++ b/app/javascript/mastodon/features/compose/components/poll_button.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { IconButton } from '../../../components/icon_button';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl } from 'react-intl';
@@ -13,7 +13,7 @@ const iconStyle = {
   lineHeight: '27px',
 };
 
-class PollButton extends React.PureComponent {
+class PollButton extends PureComponent {
 
   static propTypes = {
     disabled: PropTypes.bool,
diff --git a/app/javascript/mastodon/features/compose/components/poll_form.jsx b/app/javascript/mastodon/features/compose/components/poll_form.jsx
index 33afa3ad48..b319a2a600 100644
--- a/app/javascript/mastodon/features/compose/components/poll_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/poll_form.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
@@ -20,7 +20,7 @@ const messages = defineMessages({
   days: { id: 'intervals.full.days', defaultMessage: '{number, plural, one {# day} other {# days}}' },
 });
 
-class OptionIntl extends React.PureComponent {
+class OptionIntl extends PureComponent {
 
   static propTypes = {
     title: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
index dd20cccc28..56f4cd2533 100644
--- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
+++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { injectIntl, defineMessages } from 'react-intl';
 import { IconButton } from '../../../components/icon_button';
@@ -21,7 +21,7 @@ const messages = defineMessages({
 
 const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
 
-class PrivacyDropdownMenu extends React.PureComponent {
+class PrivacyDropdownMenu extends PureComponent {
 
   static propTypes = {
     style: PropTypes.object,
@@ -133,7 +133,7 @@ class PrivacyDropdownMenu extends React.PureComponent {
 
 }
 
-class PrivacyDropdown extends React.PureComponent {
+class PrivacyDropdown extends PureComponent {
 
   static propTypes = {
     isUserTouching: PropTypes.func,
diff --git a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx
index b3f1b1b482..8d65da62e0 100644
--- a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx
+++ b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import { Avatar } from '../../../components/avatar';
diff --git a/app/javascript/mastodon/features/compose/components/search.jsx b/app/javascript/mastodon/features/compose/components/search.jsx
index d20908b9df..92a008e221 100644
--- a/app/javascript/mastodon/features/compose/components/search.jsx
+++ b/app/javascript/mastodon/features/compose/components/search.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
@@ -12,7 +12,7 @@ const messages = defineMessages({
   placeholderSignedIn: { id: 'search.search_or_paste', defaultMessage: 'Search or paste URL' },
 });
 
-class Search extends React.PureComponent {
+class Search extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/compose/components/search_results.jsx b/app/javascript/mastodon/features/compose/components/search_results.jsx
index 9a44e2eaf7..e13889e439 100644
--- a/app/javascript/mastodon/features/compose/components/search_results.jsx
+++ b/app/javascript/mastodon/features/compose/components/search_results.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
diff --git a/app/javascript/mastodon/features/compose/components/text_icon_button.jsx b/app/javascript/mastodon/features/compose/components/text_icon_button.jsx
index 73da32ad5d..01bea732e7 100644
--- a/app/javascript/mastodon/features/compose/components/text_icon_button.jsx
+++ b/app/javascript/mastodon/features/compose/components/text_icon_button.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 
 const iconStyle = {
@@ -7,7 +7,7 @@ const iconStyle = {
   width: `${18 * 1.28571429}px`,
 };
 
-export default class TextIconButton extends React.PureComponent {
+export default class TextIconButton extends PureComponent {
 
   static propTypes = {
     label: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/compose/components/upload.jsx b/app/javascript/mastodon/features/compose/components/upload.jsx
index d667f5ef71..aeddd622d6 100644
--- a/app/javascript/mastodon/features/compose/components/upload.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import Motion from '../../ui/util/optional_motion';
diff --git a/app/javascript/mastodon/features/compose/components/upload_button.jsx b/app/javascript/mastodon/features/compose/components/upload_button.jsx
index 3870997c3d..a89c7d9878 100644
--- a/app/javascript/mastodon/features/compose/components/upload_button.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload_button.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { IconButton } from '../../../components/icon_button';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl } from 'react-intl';
diff --git a/app/javascript/mastodon/features/compose/components/upload_form.jsx b/app/javascript/mastodon/features/compose/components/upload_form.jsx
index 9ff2aa0fa6..bfa7282584 100644
--- a/app/javascript/mastodon/features/compose/components/upload_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload_form.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import UploadProgressContainer from '../containers/upload_progress_container';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/compose/components/upload_progress.jsx b/app/javascript/mastodon/features/compose/components/upload_progress.jsx
index c5740d9bf5..aa406b510a 100644
--- a/app/javascript/mastodon/features/compose/components/upload_progress.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload_progress.jsx
@@ -1,11 +1,11 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import Motion from '../../ui/util/optional_motion';
 import spring from 'react-motion/lib/spring';
 import { Icon }  from 'mastodon/components/icon';
 import { FormattedMessage } from 'react-intl';
 
-export default class UploadProgress extends React.PureComponent {
+export default class UploadProgress extends PureComponent {
 
   static propTypes = {
     active: PropTypes.bool,
diff --git a/app/javascript/mastodon/features/compose/components/warning.jsx b/app/javascript/mastodon/features/compose/components/warning.jsx
index 803b7f86ab..4947a4e28b 100644
--- a/app/javascript/mastodon/features/compose/components/warning.jsx
+++ b/app/javascript/mastodon/features/compose/components/warning.jsx
@@ -1,9 +1,9 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import Motion from '../../ui/util/optional_motion';
 import spring from 'react-motion/lib/spring';
 
-export default class Warning extends React.PureComponent {
+export default class Warning extends PureComponent {
 
   static propTypes = {
     message: PropTypes.node.isRequired,
diff --git a/app/javascript/mastodon/features/compose/containers/sensitive_button_container.jsx b/app/javascript/mastodon/features/compose/containers/sensitive_button_container.jsx
index 03f831d284..4ad938eea9 100644
--- a/app/javascript/mastodon/features/compose/containers/sensitive_button_container.jsx
+++ b/app/javascript/mastodon/features/compose/containers/sensitive_button_container.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
@@ -30,7 +30,7 @@ const mapDispatchToProps = dispatch => ({
 
 });
 
-class SensitiveButton extends React.PureComponent {
+class SensitiveButton extends PureComponent {
 
   static propTypes = {
     active: PropTypes.bool,
diff --git a/app/javascript/mastodon/features/compose/containers/warning_container.jsx b/app/javascript/mastodon/features/compose/containers/warning_container.jsx
index e99f5dacd9..6060d11edc 100644
--- a/app/javascript/mastodon/features/compose/containers/warning_container.jsx
+++ b/app/javascript/mastodon/features/compose/containers/warning_container.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import Warning from '../components/warning';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/compose/index.jsx b/app/javascript/mastodon/features/compose/index.jsx
index df60d4347e..a87f9b4d38 100644
--- a/app/javascript/mastodon/features/compose/index.jsx
+++ b/app/javascript/mastodon/features/compose/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import ComposeFormContainer from './containers/compose_form_container';
 import NavigationContainer from './containers/navigation_container';
 import PropTypes from 'prop-types';
@@ -38,7 +38,7 @@ const mapStateToProps = (state, ownProps) => ({
   showSearch: ownProps.multiColumn ? state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) : false,
 });
 
-class Compose extends React.PureComponent {
+class Compose extends PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
index 452de11619..0bd0006612 100644
--- a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversations_list.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversations_list.jsx
index 04c404e1d8..6c9dde1e37 100644
--- a/app/javascript/mastodon/features/direct_timeline/components/conversations_list.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/components/conversations_list.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/direct_timeline/index.jsx b/app/javascript/mastodon/features/direct_timeline/index.jsx
index fc45ea69a3..f836b0ebe4 100644
--- a/app/javascript/mastodon/features/direct_timeline/index.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/index.jsx
@@ -1,5 +1,5 @@
 import PropTypes from 'prop-types';
-import React from 'react';
+import { PureComponent } from 'react';
 import { Helmet } from 'react-helmet';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import { connect } from 'react-redux';
@@ -14,7 +14,7 @@ const messages = defineMessages({
   title: { id: 'column.direct', defaultMessage: 'Private mentions' },
 });
 
-class DirectTimeline extends React.PureComponent {
+class DirectTimeline extends PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/directory/components/account_card.jsx b/app/javascript/mastodon/features/directory/components/account_card.jsx
index 1ef9d64813..96a6cfa308 100644
--- a/app/javascript/mastodon/features/directory/components/account_card.jsx
+++ b/app/javascript/mastodon/features/directory/components/account_card.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/directory/index.jsx b/app/javascript/mastodon/features/directory/index.jsx
index d98a0665ac..c148937f88 100644
--- a/app/javascript/mastodon/features/directory/index.jsx
+++ b/app/javascript/mastodon/features/directory/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import { defineMessages, injectIntl } from 'react-intl';
 import PropTypes from 'prop-types';
@@ -29,7 +29,7 @@ const mapStateToProps = state => ({
   domain: state.getIn(['meta', 'domain']),
 });
 
-class Directory extends React.PureComponent {
+class Directory extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/domain_blocks/index.jsx b/app/javascript/mastodon/features/domain_blocks/index.jsx
index 6a9f6e4cf5..9189cb4d82 100644
--- a/app/javascript/mastodon/features/domain_blocks/index.jsx
+++ b/app/javascript/mastodon/features/domain_blocks/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/explore/components/story.jsx b/app/javascript/mastodon/features/explore/components/story.jsx
index 6e8db62307..1cf9df5c40 100644
--- a/app/javascript/mastodon/features/explore/components/story.jsx
+++ b/app/javascript/mastodon/features/explore/components/story.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import { Blurhash } from 'mastodon/components/blurhash';
 import { accountsCountRenderer } from 'mastodon/components/hashtag';
@@ -6,7 +6,7 @@ import ShortNumber from 'mastodon/components/short_number';
 import { Skeleton } from 'mastodon/components/skeleton';
 import classNames from 'classnames';
 
-export default class Story extends React.PureComponent {
+export default class Story extends PureComponent {
 
   static propTypes = {
     url: PropTypes.string,
@@ -38,10 +38,10 @@ export default class Story extends React.PureComponent {
 
         <div className='story__thumbnail'>
           {thumbnail ? (
-            <React.Fragment>
+            <Fragment>
               <div className={classNames('story__thumbnail__preview', { 'story__thumbnail__preview--hidden': thumbnailLoaded })}><Blurhash hash={blurhash} /></div>
               <img src={thumbnail} onLoad={this.handleImageLoad} alt='' role='presentation' />
-            </React.Fragment>
+            </Fragment>
           ) : <Skeleton />}
         </div>
       </a>
diff --git a/app/javascript/mastodon/features/explore/index.jsx b/app/javascript/mastodon/features/explore/index.jsx
index 35626226ec..f858ee572f 100644
--- a/app/javascript/mastodon/features/explore/index.jsx
+++ b/app/javascript/mastodon/features/explore/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
@@ -24,7 +24,7 @@ const mapStateToProps = state => ({
   isSearching: state.getIn(['search', 'submitted']) || !showTrends,
 });
 
-class Explore extends React.PureComponent {
+class Explore extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/explore/links.jsx b/app/javascript/mastodon/features/explore/links.jsx
index 1937399161..5fa3a29853 100644
--- a/app/javascript/mastodon/features/explore/links.jsx
+++ b/app/javascript/mastodon/features/explore/links.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import Story from './components/story';
@@ -13,7 +13,7 @@ const mapStateToProps = state => ({
   isLoading: state.getIn(['trends', 'links', 'isLoading']),
 });
 
-class Links extends React.PureComponent {
+class Links extends PureComponent {
 
   static propTypes = {
     links: ImmutablePropTypes.list,
diff --git a/app/javascript/mastodon/features/explore/results.jsx b/app/javascript/mastodon/features/explore/results.jsx
index 9725cf35cd..103cb44787 100644
--- a/app/javascript/mastodon/features/explore/results.jsx
+++ b/app/javascript/mastodon/features/explore/results.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
@@ -42,7 +42,7 @@ const renderStatuses = (results, onLoadMore) => appendLoadMore('statuses', resul
   <Status key={`status-${item}`} id={item} />
 )), onLoadMore);
 
-class Results extends React.PureComponent {
+class Results extends PureComponent {
 
   static propTypes = {
     results: ImmutablePropTypes.map,
@@ -102,7 +102,7 @@ class Results extends React.PureComponent {
     }
 
     return (
-      <React.Fragment>
+      <Fragment>
         <div className='account__section-headline'>
           <button onClick={this.handleSelectAll} className={type === 'all' && 'active'}><FormattedMessage id='search_results.all' defaultMessage='All' /></button>
           <button onClick={this.handleSelectAccounts} className={type === 'accounts' && 'active'}><FormattedMessage id='search_results.accounts' defaultMessage='Profiles' /></button>
@@ -117,7 +117,7 @@ class Results extends React.PureComponent {
         <Helmet>
           <title>{intl.formatMessage(messages.title, { q })}</title>
         </Helmet>
-      </React.Fragment>
+      </Fragment>
     );
   }
 
diff --git a/app/javascript/mastodon/features/explore/statuses.jsx b/app/javascript/mastodon/features/explore/statuses.jsx
index a98a6d0465..1a606bb3b9 100644
--- a/app/javascript/mastodon/features/explore/statuses.jsx
+++ b/app/javascript/mastodon/features/explore/statuses.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import StatusList from 'mastodon/components/status_list';
@@ -14,7 +14,7 @@ const mapStateToProps = state => ({
   hasMore: !!state.getIn(['status_lists', 'trending', 'next']),
 });
 
-class Statuses extends React.PureComponent {
+class Statuses extends PureComponent {
 
   static propTypes = {
     statusIds: ImmutablePropTypes.list,
diff --git a/app/javascript/mastodon/features/explore/suggestions.jsx b/app/javascript/mastodon/features/explore/suggestions.jsx
index 53eb7ba4b4..b7c15b4d25 100644
--- a/app/javascript/mastodon/features/explore/suggestions.jsx
+++ b/app/javascript/mastodon/features/explore/suggestions.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import AccountCard from 'mastodon/features/directory/components/account_card';
@@ -12,7 +12,7 @@ const mapStateToProps = state => ({
   isLoading: state.getIn(['suggestions', 'isLoading']),
 });
 
-class Suggestions extends React.PureComponent {
+class Suggestions extends PureComponent {
 
   static propTypes = {
     isLoading: PropTypes.bool,
diff --git a/app/javascript/mastodon/features/explore/tags.jsx b/app/javascript/mastodon/features/explore/tags.jsx
index 3ba813c3f8..607420b9d5 100644
--- a/app/javascript/mastodon/features/explore/tags.jsx
+++ b/app/javascript/mastodon/features/explore/tags.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { ImmutableHashtag as Hashtag } from 'mastodon/components/hashtag';
@@ -13,7 +13,7 @@ const mapStateToProps = state => ({
   isLoadingHashtags: state.getIn(['trends', 'tags', 'isLoading']),
 });
 
-class Tags extends React.PureComponent {
+class Tags extends PureComponent {
 
   static propTypes = {
     hashtags: ImmutablePropTypes.list,
diff --git a/app/javascript/mastodon/features/favourited_statuses/index.jsx b/app/javascript/mastodon/features/favourited_statuses/index.jsx
index 161297114d..17369617f3 100644
--- a/app/javascript/mastodon/features/favourited_statuses/index.jsx
+++ b/app/javascript/mastodon/features/favourited_statuses/index.jsx
@@ -1,6 +1,5 @@
 import { debounce } from 'lodash';
 import PropTypes from 'prop-types';
-import React from 'react';
 import { Helmet } from 'react-helmet';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/favourites/index.jsx b/app/javascript/mastodon/features/favourites/index.jsx
index ed210dad5b..85d8686d19 100644
--- a/app/javascript/mastodon/features/favourites/index.jsx
+++ b/app/javascript/mastodon/features/favourites/index.jsx
@@ -1,5 +1,4 @@
 import PropTypes from 'prop-types';
-import React from 'react';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
diff --git a/app/javascript/mastodon/features/filters/added_to_filter.jsx b/app/javascript/mastodon/features/filters/added_to_filter.jsx
index d935d96e29..139832ee98 100644
--- a/app/javascript/mastodon/features/filters/added_to_filter.jsx
+++ b/app/javascript/mastodon/features/filters/added_to_filter.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { FormattedMessage } from 'react-intl';
@@ -10,7 +10,7 @@ const mapStateToProps = (state, { filterId }) => ({
   filter: state.getIn(['filters', filterId]),
 });
 
-class AddedToFilter extends React.PureComponent {
+class AddedToFilter extends PureComponent {
 
   static propTypes = {
     onClose: PropTypes.func.isRequired,
@@ -30,7 +30,7 @@ class AddedToFilter extends React.PureComponent {
     let expiredMessage = null;
     if (filter.get('expires_at') && filter.get('expires_at') < new Date()) {
       expiredMessage = (
-        <React.Fragment>
+        <Fragment>
           <h4 className='report-dialog-modal__subtitle'><FormattedMessage id='filter_modal.added.expired_title' defaultMessage='Expired filter!' /></h4>
           <p className='report-dialog-modal__lead'>
             <FormattedMessage
@@ -38,14 +38,14 @@ class AddedToFilter extends React.PureComponent {
               defaultMessage='This filter category has expired, you will need to change the expiration date for it to apply.'
             />
           </p>
-        </React.Fragment>
+        </Fragment>
       );
     }
 
     let contextMismatchMessage = null;
     if (contextType && !filter.get('context').includes(toServerSideType(contextType))) {
       contextMismatchMessage = (
-        <React.Fragment>
+        <Fragment>
           <h4 className='report-dialog-modal__subtitle'><FormattedMessage id='filter_modal.added.context_mismatch_title' defaultMessage='Context mismatch!' /></h4>
           <p className='report-dialog-modal__lead'>
             <FormattedMessage
@@ -53,7 +53,7 @@ class AddedToFilter extends React.PureComponent {
               defaultMessage='This filter category does not apply to the context in which you have accessed this post. If you want the post to be filtered in this context too, you will have to edit the filter.'
             />
           </p>
-        </React.Fragment>
+        </Fragment>
       );
     }
 
@@ -67,7 +67,7 @@ class AddedToFilter extends React.PureComponent {
     );
 
     return (
-      <React.Fragment>
+      <Fragment>
         <h3 className='report-dialog-modal__title'><FormattedMessage id='filter_modal.added.title' defaultMessage='Filter added!' /></h3>
         <p className='report-dialog-modal__lead'>
           <FormattedMessage
@@ -94,7 +94,7 @@ class AddedToFilter extends React.PureComponent {
         <div className='report-dialog-modal__actions'>
           <Button onClick={this.handleCloseClick}><FormattedMessage id='report.close' defaultMessage='Done' /></Button>
         </div>
-      </React.Fragment>
+      </Fragment>
     );
   }
 
diff --git a/app/javascript/mastodon/features/filters/select_filter.jsx b/app/javascript/mastodon/features/filters/select_filter.jsx
index 618f875dbe..6d23d48cf2 100644
--- a/app/javascript/mastodon/features/filters/select_filter.jsx
+++ b/app/javascript/mastodon/features/filters/select_filter.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import { connect } from 'react-redux';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
@@ -22,7 +22,7 @@ const mapStateToProps = (state, { contextType }) => ({
   ]),
 });
 
-class SelectFilter extends React.PureComponent {
+class SelectFilter extends PureComponent {
 
   static propTypes = {
     onSelectFilter: PropTypes.func.isRequired,
@@ -169,7 +169,7 @@ class SelectFilter extends React.PureComponent {
     const results = this.search();
 
     return (
-      <React.Fragment>
+      <Fragment>
         <h3 className='report-dialog-modal__title'><FormattedMessage id='filter_modal.select_filter.title' defaultMessage='Filter this post' /></h3>
         <p className='report-dialog-modal__lead'><FormattedMessage id='filter_modal.select_filter.subtitle' defaultMessage='Use an existing category or create a new one' /></p>
 
@@ -183,7 +183,7 @@ class SelectFilter extends React.PureComponent {
           {isSearching && this.renderCreateNew(searchValue) }
         </div>
 
-      </React.Fragment>
+      </Fragment>
     );
   }
 
diff --git a/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx b/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
index 5d0632b0f6..4cc46fb27f 100644
--- a/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
+++ b/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { Link } from 'react-router-dom';
diff --git a/app/javascript/mastodon/features/follow_requests/index.jsx b/app/javascript/mastodon/features/follow_requests/index.jsx
index 779bc473e4..c592664618 100644
--- a/app/javascript/mastodon/features/follow_requests/index.jsx
+++ b/app/javascript/mastodon/features/follow_requests/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/followed_tags/index.jsx b/app/javascript/mastodon/features/followed_tags/index.jsx
index 7c53542c2e..e3bceed726 100644
--- a/app/javascript/mastodon/features/followed_tags/index.jsx
+++ b/app/javascript/mastodon/features/followed_tags/index.jsx
@@ -1,6 +1,5 @@
 import { debounce } from 'lodash';
 import PropTypes from 'prop-types';
-import React from 'react';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
diff --git a/app/javascript/mastodon/features/followers/index.jsx b/app/javascript/mastodon/features/followers/index.jsx
index 1a1fdf578b..bbf9cd71ee 100644
--- a/app/javascript/mastodon/features/followers/index.jsx
+++ b/app/javascript/mastodon/features/followers/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/following/index.jsx b/app/javascript/mastodon/features/following/index.jsx
index c024ff063b..c1463c895a 100644
--- a/app/javascript/mastodon/features/following/index.jsx
+++ b/app/javascript/mastodon/features/following/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/getting_started/components/announcements.jsx b/app/javascript/mastodon/features/getting_started/components/announcements.jsx
index ab29e3dc86..44fc25d206 100644
--- a/app/javascript/mastodon/features/getting_started/components/announcements.jsx
+++ b/app/javascript/mastodon/features/getting_started/components/announcements.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import ReactSwipeableViews from 'react-swipeable-views';
 import ImmutablePropTypes from 'react-immutable-proptypes';
@@ -148,7 +148,7 @@ class Content extends ImmutablePureComponent {
 
 }
 
-class Emoji extends React.PureComponent {
+class Emoji extends PureComponent {
 
   static propTypes = {
     emoji: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/getting_started/components/trends.jsx b/app/javascript/mastodon/features/getting_started/components/trends.jsx
index 8dcdb4f61c..59596b5546 100644
--- a/app/javascript/mastodon/features/getting_started/components/trends.jsx
+++ b/app/javascript/mastodon/features/getting_started/components/trends.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
diff --git a/app/javascript/mastodon/features/getting_started/index.jsx b/app/javascript/mastodon/features/getting_started/index.jsx
index 29659acc73..69c4fb502f 100644
--- a/app/javascript/mastodon/features/getting_started/index.jsx
+++ b/app/javascript/mastodon/features/getting_started/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import Column from 'mastodon/components/column';
 import ColumnHeader from 'mastodon/components/column_header';
 import ColumnLink from '../ui/components/column_link';
diff --git a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.jsx b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.jsx
index f140f2d013..528d4309fc 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.jsx
+++ b/app/javascript/mastodon/features/hashtag_timeline/components/column_settings.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
@@ -12,7 +12,7 @@ const messages = defineMessages({
   noOptions: { id: 'hashtag.column_settings.select.no_options_message', defaultMessage: 'No suggestions found' },
 });
 
-class ColumnSettings extends React.PureComponent {
+class ColumnSettings extends PureComponent {
 
   static propTypes = {
     settings: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.jsx b/app/javascript/mastodon/features/hashtag_timeline/index.jsx
index 116a5921c1..29507ee46f 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/index.jsx
+++ b/app/javascript/mastodon/features/hashtag_timeline/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
@@ -26,7 +26,7 @@ const mapStateToProps = (state, props) => ({
   tag: state.getIn(['tags', props.params.id]),
 });
 
-class HashtagTimeline extends React.PureComponent {
+class HashtagTimeline extends PureComponent {
 
   disconnects = [];
 
diff --git a/app/javascript/mastodon/features/home_timeline/components/column_settings.jsx b/app/javascript/mastodon/features/home_timeline/components/column_settings.jsx
index bd15390c0b..d78918d6eb 100644
--- a/app/javascript/mastodon/features/home_timeline/components/column_settings.jsx
+++ b/app/javascript/mastodon/features/home_timeline/components/column_settings.jsx
@@ -1,10 +1,10 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { injectIntl, FormattedMessage } from 'react-intl';
 import SettingToggle from '../../notifications/components/setting_toggle';
 
-class ColumnSettings extends React.PureComponent {
+class ColumnSettings extends PureComponent {
 
   static propTypes = {
     settings: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/home_timeline/index.jsx b/app/javascript/mastodon/features/home_timeline/index.jsx
index 26166b254c..9735699f94 100644
--- a/app/javascript/mastodon/features/home_timeline/index.jsx
+++ b/app/javascript/mastodon/features/home_timeline/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import { expandHomeTimeline } from '../../actions/timelines';
 import PropTypes from 'prop-types';
@@ -30,7 +30,7 @@ const mapStateToProps = state => ({
   showAnnouncements: state.getIn(['announcements', 'show']),
 });
 
-class HomeTimeline extends React.PureComponent {
+class HomeTimeline extends PureComponent {
 
   static contextTypes = {
     identity: PropTypes.object,
diff --git a/app/javascript/mastodon/features/interaction_modal/index.jsx b/app/javascript/mastodon/features/interaction_modal/index.jsx
index d9eff63cba..0f3b36122b 100644
--- a/app/javascript/mastodon/features/interaction_modal/index.jsx
+++ b/app/javascript/mastodon/features/interaction_modal/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { FormattedMessage } from 'react-intl';
 import { registrationsOpen } from 'mastodon/initial_state';
@@ -18,7 +18,7 @@ const mapDispatchToProps = (dispatch) => ({
   },
 });
 
-class Copypaste extends React.PureComponent {
+class Copypaste extends PureComponent {
 
   static propTypes = {
     value: PropTypes.string,
@@ -74,7 +74,7 @@ class Copypaste extends React.PureComponent {
 
 }
 
-class InteractionModal extends React.PureComponent {
+class InteractionModal extends PureComponent {
 
   static propTypes = {
     displayNameHtml: PropTypes.string,
diff --git a/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx b/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx
index 70f019712e..542d147e1d 100644
--- a/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx
+++ b/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import Column from 'mastodon/components/column';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/list_adder/components/account.jsx b/app/javascript/mastodon/features/list_adder/components/account.jsx
index 5dc384aba6..e2828f5ab3 100644
--- a/app/javascript/mastodon/features/list_adder/components/account.jsx
+++ b/app/javascript/mastodon/features/list_adder/components/account.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { makeGetAccount } from '../../../selectors';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/list_adder/components/list.jsx b/app/javascript/mastodon/features/list_adder/components/list.jsx
index 954a4a5cfe..d7f2a9f166 100644
--- a/app/javascript/mastodon/features/list_adder/components/list.jsx
+++ b/app/javascript/mastodon/features/list_adder/components/list.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import { connect } from 'react-redux';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/list_adder/index.jsx b/app/javascript/mastodon/features/list_adder/index.jsx
index 45d5589f96..3ef29b212e 100644
--- a/app/javascript/mastodon/features/list_adder/index.jsx
+++ b/app/javascript/mastodon/features/list_adder/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { connect } from 'react-redux';
diff --git a/app/javascript/mastodon/features/list_editor/components/account.jsx b/app/javascript/mastodon/features/list_editor/components/account.jsx
index fc1d2d6071..6ce59bc371 100644
--- a/app/javascript/mastodon/features/list_editor/components/account.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/account.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import { connect } from 'react-redux';
 import { makeGetAccount } from '../../../selectors';
diff --git a/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx b/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx
index 65bfe7f94a..7153281085 100644
--- a/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import { changeListEditorTitle, submitListEditor } from '../../../actions/lists';
@@ -19,7 +19,7 @@ const mapDispatchToProps = dispatch => ({
   onSubmit: () => dispatch(submitListEditor(false)),
 });
 
-class ListForm extends React.PureComponent {
+class ListForm extends PureComponent {
 
   static propTypes = {
     value: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/list_editor/components/search.jsx b/app/javascript/mastodon/features/list_editor/components/search.jsx
index 59e4c7d939..bc5cd136ff 100644
--- a/app/javascript/mastodon/features/list_editor/components/search.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/search.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { connect } from 'react-redux';
 import { defineMessages, injectIntl } from 'react-intl';
@@ -20,7 +20,7 @@ const mapDispatchToProps = dispatch => ({
   onChange: value => dispatch(changeListSuggestions(value)),
 });
 
-class Search extends React.PureComponent {
+class Search extends PureComponent {
 
   static propTypes = {
     intl: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/list_editor/index.jsx b/app/javascript/mastodon/features/list_editor/index.jsx
index ed9d091326..3ed390c616 100644
--- a/app/javascript/mastodon/features/list_editor/index.jsx
+++ b/app/javascript/mastodon/features/list_editor/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { connect } from 'react-redux';
diff --git a/app/javascript/mastodon/features/list_timeline/index.jsx b/app/javascript/mastodon/features/list_timeline/index.jsx
index e1408d8efb..86d6e3881b 100644
--- a/app/javascript/mastodon/features/list_timeline/index.jsx
+++ b/app/javascript/mastodon/features/list_timeline/index.jsx
@@ -1,5 +1,5 @@
 import PropTypes from 'prop-types';
-import React from 'react';
+import { PureComponent } from 'react';
 import { Helmet } from 'react-helmet';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
@@ -30,7 +30,7 @@ const mapStateToProps = (state, props) => ({
   hasUnread: state.getIn(['timelines', `list:${props.params.id}`, 'unread']) > 0,
 });
 
-class ListTimeline extends React.PureComponent {
+class ListTimeline extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/lists/components/new_list_form.jsx b/app/javascript/mastodon/features/lists/components/new_list_form.jsx
index 50b52518e9..cab1168265 100644
--- a/app/javascript/mastodon/features/lists/components/new_list_form.jsx
+++ b/app/javascript/mastodon/features/lists/components/new_list_form.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import { changeListEditorTitle, submitListEditor } from 'mastodon/actions/lists';
@@ -20,7 +20,7 @@ const mapDispatchToProps = dispatch => ({
   onSubmit: () => dispatch(submitListEditor(true)),
 });
 
-class NewListForm extends React.PureComponent {
+class NewListForm extends PureComponent {
 
   static propTypes = {
     value: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/lists/index.jsx b/app/javascript/mastodon/features/lists/index.jsx
index 232b0c2d5a..6e741759d0 100644
--- a/app/javascript/mastodon/features/lists/index.jsx
+++ b/app/javascript/mastodon/features/lists/index.jsx
@@ -1,5 +1,4 @@
 import PropTypes from 'prop-types';
-import React from 'react';
 import { Helmet } from 'react-helmet';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/mutes/index.jsx b/app/javascript/mastodon/features/mutes/index.jsx
index 078d8779ec..e5c6fbbec9 100644
--- a/app/javascript/mastodon/features/mutes/index.jsx
+++ b/app/javascript/mastodon/features/mutes/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx b/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
index e043f5ee1e..342f6a3fb0 100644
--- a/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
+++ b/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
@@ -1,9 +1,9 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { FormattedMessage } from 'react-intl';
 import { Icon }  from 'mastodon/components/icon';
 
-export default class ClearColumnButton extends React.PureComponent {
+export default class ClearColumnButton extends PureComponent {
 
   static propTypes = {
     onClick: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/notifications/components/column_settings.jsx b/app/javascript/mastodon/features/notifications/components/column_settings.jsx
index 9251847bad..42a0eb827f 100644
--- a/app/javascript/mastodon/features/notifications/components/column_settings.jsx
+++ b/app/javascript/mastodon/features/notifications/components/column_settings.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { FormattedMessage } from 'react-intl';
@@ -7,7 +7,7 @@ import GrantPermissionButton from './grant_permission_button';
 import SettingToggle from './setting_toggle';
 import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_REPORTS } from 'mastodon/permissions';
 
-export default class ColumnSettings extends React.PureComponent {
+export default class ColumnSettings extends PureComponent {
 
   static contextTypes = {
     identity: PropTypes.object,
diff --git a/app/javascript/mastodon/features/notifications/components/filter_bar.jsx b/app/javascript/mastodon/features/notifications/components/filter_bar.jsx
index f16c84f97a..2a04716414 100644
--- a/app/javascript/mastodon/features/notifications/components/filter_bar.jsx
+++ b/app/javascript/mastodon/features/notifications/components/filter_bar.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import { Icon }  from 'mastodon/components/icon';
@@ -12,7 +12,7 @@ const tooltips = defineMessages({
   statuses: { id: 'notifications.filter.statuses', defaultMessage: 'Updates from people you follow' },
 });
 
-class FilterBar extends React.PureComponent {
+class FilterBar extends PureComponent {
 
   static propTypes = {
     selectFilter: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/notifications/components/follow_request.jsx b/app/javascript/mastodon/features/notifications/components/follow_request.jsx
index d8b2ca1cc9..9456c29add 100644
--- a/app/javascript/mastodon/features/notifications/components/follow_request.jsx
+++ b/app/javascript/mastodon/features/notifications/components/follow_request.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { Fragment } from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import { Avatar } from 'mastodon/components/avatar';
@@ -31,10 +31,10 @@ class FollowRequest extends ImmutablePureComponent {
 
     if (hidden) {
       return (
-        <React.Fragment>
+        <Fragment>
           {account.get('display_name')}
           {account.get('username')}
-        </React.Fragment>
+        </Fragment>
       );
     }
 
diff --git a/app/javascript/mastodon/features/notifications/components/grant_permission_button.jsx b/app/javascript/mastodon/features/notifications/components/grant_permission_button.jsx
index 5b2db48fdb..96f5d67d9c 100644
--- a/app/javascript/mastodon/features/notifications/components/grant_permission_button.jsx
+++ b/app/javascript/mastodon/features/notifications/components/grant_permission_button.jsx
@@ -1,8 +1,8 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { FormattedMessage } from 'react-intl';
 
-export default class GrantPermissionButton extends React.PureComponent {
+export default class GrantPermissionButton extends PureComponent {
 
   static propTypes = {
     onClick: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx
index 0f1aef8db1..7d5b18554e 100644
--- a/app/javascript/mastodon/features/notifications/components/notification.jsx
+++ b/app/javascript/mastodon/features/notifications/components/notification.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { injectIntl, FormattedMessage, defineMessages } from 'react-intl';
 import { HotKeys } from 'react-hotkeys';
diff --git a/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx b/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx
index a1b4248e7c..d42b350b71 100644
--- a/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx
+++ b/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { Icon }  from 'mastodon/components/icon';
 import Button from 'mastodon/components/button';
 import { IconButton } from 'mastodon/components/icon_button';
@@ -12,7 +12,7 @@ const messages = defineMessages({
   close: { id: 'lightbox.close', defaultMessage: 'Close' },
 });
 
-class NotificationsPermissionBanner extends React.PureComponent {
+class NotificationsPermissionBanner extends PureComponent {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/notifications/components/report.jsx b/app/javascript/mastodon/features/notifications/components/report.jsx
index 1c0e1a7750..301a9525a9 100644
--- a/app/javascript/mastodon/features/notifications/components/report.jsx
+++ b/app/javascript/mastodon/features/notifications/components/report.jsx
@@ -1,4 +1,4 @@
-import React, { Fragment } from 'react';
+import { Fragment } from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
diff --git a/app/javascript/mastodon/features/notifications/components/setting_toggle.jsx b/app/javascript/mastodon/features/notifications/components/setting_toggle.jsx
index c979e4383b..7eec664a10 100644
--- a/app/javascript/mastodon/features/notifications/components/setting_toggle.jsx
+++ b/app/javascript/mastodon/features/notifications/components/setting_toggle.jsx
@@ -1,9 +1,9 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import Toggle from 'react-toggle';
 
-export default class SettingToggle extends React.PureComponent {
+export default class SettingToggle extends PureComponent {
 
   static propTypes = {
     prefix: PropTypes.string,
diff --git a/app/javascript/mastodon/features/notifications/index.jsx b/app/javascript/mastodon/features/notifications/index.jsx
index 8b77374c40..5375013d19 100644
--- a/app/javascript/mastodon/features/notifications/index.jsx
+++ b/app/javascript/mastodon/features/notifications/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
@@ -67,7 +67,7 @@ const mapStateToProps = state => ({
   needsNotificationPermission: state.getIn(['settings', 'notifications', 'alerts']).includes(true) && state.getIn(['notifications', 'browserSupport']) && state.getIn(['notifications', 'browserPermission']) === 'default' && !state.getIn(['settings', 'notifications', 'dismissPermissionBanner']),
 });
 
-class Notifications extends React.PureComponent {
+class Notifications extends PureComponent {
 
   static contextTypes = {
     identity: PropTypes.object,
diff --git a/app/javascript/mastodon/features/onboarding/components/arrow_small_right.jsx b/app/javascript/mastodon/features/onboarding/components/arrow_small_right.jsx
index 40e166f6dc..79b9db383f 100644
--- a/app/javascript/mastodon/features/onboarding/components/arrow_small_right.jsx
+++ b/app/javascript/mastodon/features/onboarding/components/arrow_small_right.jsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 const ArrowSmallRight = () => (
   <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='currentColor'>
     <path fillRule='evenodd' d='M5 10a.75.75 0 01.75-.75h6.638L10.23 7.29a.75.75 0 111.04-1.08l3.5 3.25a.75.75 0 010 1.08l-3.5 3.25a.75.75 0 11-1.04-1.08l2.158-1.96H5.75A.75.75 0 015 10z' clipRule='evenodd' />
diff --git a/app/javascript/mastodon/features/onboarding/components/progress_indicator.jsx b/app/javascript/mastodon/features/onboarding/components/progress_indicator.jsx
index 7d75e50edb..0d62f4e949 100644
--- a/app/javascript/mastodon/features/onboarding/components/progress_indicator.jsx
+++ b/app/javascript/mastodon/features/onboarding/components/progress_indicator.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { Fragment } from 'react';
 import PropTypes from 'prop-types';
 import { Check } from 'mastodon/components/check';
 import classNames from 'classnames';
@@ -6,13 +6,13 @@ import classNames from 'classnames';
 const ProgressIndicator = ({ steps, completed }) => (
   <div className='onboarding__progress-indicator'>
     {(new Array(steps)).fill().map((_, i) => (
-      <React.Fragment key={i}>
+      <Fragment key={i}>
         {i > 0 && <div className={classNames('onboarding__progress-indicator__line', { active: completed > i })} />}
 
         <div className={classNames('onboarding__progress-indicator__step', { active: completed > i })}>
           {completed > i && <Check />}
         </div>
-      </React.Fragment>
+      </Fragment>
     ))}
   </div>
 );
diff --git a/app/javascript/mastodon/features/onboarding/components/step.jsx b/app/javascript/mastodon/features/onboarding/components/step.jsx
index 38e4b564a8..e612f681e8 100644
--- a/app/javascript/mastodon/features/onboarding/components/step.jsx
+++ b/app/javascript/mastodon/features/onboarding/components/step.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import { Icon }  from 'mastodon/components/icon';
 import { Check } from 'mastodon/components/check';
diff --git a/app/javascript/mastodon/features/onboarding/follows.jsx b/app/javascript/mastodon/features/onboarding/follows.jsx
index c96c69055b..30e7b14190 100644
--- a/app/javascript/mastodon/features/onboarding/follows.jsx
+++ b/app/javascript/mastodon/features/onboarding/follows.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import Column from 'mastodon/components/column';
 import ColumnBackButton from 'mastodon/components/column_back_button';
 import PropTypes from 'prop-types';
@@ -23,7 +23,7 @@ const mapStateToProps = () => {
   });
 };
 
-class Follows extends React.PureComponent {
+class Follows extends PureComponent {
 
   static propTypes = {
     onBack: PropTypes.func,
diff --git a/app/javascript/mastodon/features/onboarding/index.jsx b/app/javascript/mastodon/features/onboarding/index.jsx
index ca4a8bcf13..e9018f15e7 100644
--- a/app/javascript/mastodon/features/onboarding/index.jsx
+++ b/app/javascript/mastodon/features/onboarding/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import ImmutablePropTypes from 'react-immutable-proptypes';
diff --git a/app/javascript/mastodon/features/onboarding/share.jsx b/app/javascript/mastodon/features/onboarding/share.jsx
index 82fdada413..30e148379d 100644
--- a/app/javascript/mastodon/features/onboarding/share.jsx
+++ b/app/javascript/mastodon/features/onboarding/share.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import Column from 'mastodon/components/column';
 import ColumnBackButton from 'mastodon/components/column_back_button';
 import PropTypes from 'prop-types';
@@ -20,7 +20,7 @@ const mapStateToProps = state => ({
   account: state.getIn(['accounts', me]),
 });
 
-class CopyPasteText extends React.PureComponent {
+class CopyPasteText extends PureComponent {
 
   static propTypes = {
     value: PropTypes.string,
@@ -81,7 +81,7 @@ class CopyPasteText extends React.PureComponent {
 
 }
 
-class TipCarousel extends React.PureComponent {
+class TipCarousel extends PureComponent {
 
   static propTypes = {
     children: PropTypes.node,
@@ -135,7 +135,7 @@ class TipCarousel extends React.PureComponent {
 
 }
 
-class Share extends React.PureComponent {
+class Share extends PureComponent {
 
   static propTypes = {
     onBack: PropTypes.func,
diff --git a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
index 5c60284d65..eddddf48a9 100644
--- a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
+++ b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import ImmutablePropTypes from 'react-immutable-proptypes';
diff --git a/app/javascript/mastodon/features/picture_in_picture/components/header.jsx b/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
index c1c04da548..4339c318dc 100644
--- a/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
+++ b/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import ImmutablePropTypes from 'react-immutable-proptypes';
diff --git a/app/javascript/mastodon/features/picture_in_picture/index.jsx b/app/javascript/mastodon/features/picture_in_picture/index.jsx
index ae48a1b4e5..788a302e9d 100644
--- a/app/javascript/mastodon/features/picture_in_picture/index.jsx
+++ b/app/javascript/mastodon/features/picture_in_picture/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { Component } from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import Video from 'mastodon/features/video';
@@ -11,7 +11,7 @@ const mapStateToProps = state => ({
   ...state.get('picture_in_picture'),
 });
 
-class PictureInPicture extends React.Component {
+class PictureInPicture extends Component {
 
   static propTypes = {
     statusId: PropTypes.string,
diff --git a/app/javascript/mastodon/features/pinned_statuses/index.jsx b/app/javascript/mastodon/features/pinned_statuses/index.jsx
index e58ce2bb89..9ac9c2f595 100644
--- a/app/javascript/mastodon/features/pinned_statuses/index.jsx
+++ b/app/javascript/mastodon/features/pinned_statuses/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
diff --git a/app/javascript/mastodon/features/privacy_policy/index.jsx b/app/javascript/mastodon/features/privacy_policy/index.jsx
index 07a6914989..10ec31c146 100644
--- a/app/javascript/mastodon/features/privacy_policy/index.jsx
+++ b/app/javascript/mastodon/features/privacy_policy/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { Helmet } from 'react-helmet';
 import { FormattedMessage, FormattedDate, injectIntl, defineMessages } from 'react-intl';
@@ -10,7 +10,7 @@ const messages = defineMessages({
   title: { id: 'privacy_policy.title', defaultMessage: 'Privacy Policy' },
 });
 
-class PrivacyPolicy extends React.PureComponent {
+class PrivacyPolicy extends PureComponent {
 
   static propTypes = {
     intl: PropTypes.object,
diff --git a/app/javascript/mastodon/features/public_timeline/components/column_settings.jsx b/app/javascript/mastodon/features/public_timeline/components/column_settings.jsx
index bf8a8323e0..34db9149cb 100644
--- a/app/javascript/mastodon/features/public_timeline/components/column_settings.jsx
+++ b/app/javascript/mastodon/features/public_timeline/components/column_settings.jsx
@@ -1,10 +1,10 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { injectIntl, FormattedMessage } from 'react-intl';
 import SettingToggle from '../../notifications/components/setting_toggle';
 
-class ColumnSettings extends React.PureComponent {
+class ColumnSettings extends PureComponent {
 
   static propTypes = {
     settings: ImmutablePropTypes.map.isRequired,
diff --git a/app/javascript/mastodon/features/public_timeline/index.jsx b/app/javascript/mastodon/features/public_timeline/index.jsx
index f89caa2c95..f61faa1e7f 100644
--- a/app/javascript/mastodon/features/public_timeline/index.jsx
+++ b/app/javascript/mastodon/features/public_timeline/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import PropTypes from 'prop-types';
@@ -31,7 +31,7 @@ const mapStateToProps = (state, { columnId }) => {
   };
 };
 
-class PublicTimeline extends React.PureComponent {
+class PublicTimeline extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/reblogs/index.jsx b/app/javascript/mastodon/features/reblogs/index.jsx
index 757ef0dd0e..2248098863 100644
--- a/app/javascript/mastodon/features/reblogs/index.jsx
+++ b/app/javascript/mastodon/features/reblogs/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/report/category.jsx b/app/javascript/mastodon/features/report/category.jsx
index 492a533f20..f1fbd9622d 100644
--- a/app/javascript/mastodon/features/report/category.jsx
+++ b/app/javascript/mastodon/features/report/category.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { connect } from 'react-redux';
@@ -24,7 +24,7 @@ const mapStateToProps = state => ({
   rules: state.getIn(['server', 'server', 'rules'], ImmutableList()),
 });
 
-class Category extends React.PureComponent {
+class Category extends PureComponent {
 
   static propTypes = {
     onNextStep: PropTypes.func.isRequired,
@@ -74,7 +74,7 @@ class Category extends React.PureComponent {
     ];
 
     return (
-      <React.Fragment>
+      <Fragment>
         <h3 className='report-dialog-modal__title'><FormattedMessage id='report.category.title' defaultMessage="Tell us what's going on with this {type}" values={{ type: intl.formatMessage(messages[startedFrom]) }} /></h3>
         <p className='report-dialog-modal__lead'><FormattedMessage id='report.category.subtitle' defaultMessage='Choose the best match' /></p>
 
@@ -97,7 +97,7 @@ class Category extends React.PureComponent {
         <div className='report-dialog-modal__actions'>
           <Button onClick={this.handleNextClick} disabled={category === null}><FormattedMessage id='report.next' defaultMessage='Next' /></Button>
         </div>
-      </React.Fragment>
+      </Fragment>
     );
   }
 
diff --git a/app/javascript/mastodon/features/report/comment.jsx b/app/javascript/mastodon/features/report/comment.jsx
index ab29f6c227..6cf43fca0d 100644
--- a/app/javascript/mastodon/features/report/comment.jsx
+++ b/app/javascript/mastodon/features/report/comment.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import { injectIntl, defineMessages, FormattedMessage } from 'react-intl';
 import Button from 'mastodon/components/button';
@@ -8,7 +8,7 @@ const messages = defineMessages({
   placeholder: { id: 'report.placeholder', defaultMessage: 'Type or paste additional comments' },
 });
 
-class Comment extends React.PureComponent {
+class Comment extends PureComponent {
 
   static propTypes = {
     onSubmit: PropTypes.func.isRequired,
@@ -47,7 +47,7 @@ class Comment extends React.PureComponent {
     const { comment, isRemote, forward, domain, isSubmitting, intl } = this.props;
 
     return (
-      <React.Fragment>
+      <Fragment>
         <h3 className='report-dialog-modal__title'><FormattedMessage id='report.comment.title' defaultMessage='Is there anything else you think we should know?' /></h3>
 
         <textarea
@@ -60,14 +60,14 @@ class Comment extends React.PureComponent {
         />
 
         {isRemote && (
-          <React.Fragment>
+          <Fragment>
             <p className='report-dialog-modal__lead'><FormattedMessage id='report.forward_hint' defaultMessage='The account is from another server. Send an anonymized copy of the report there as well?' /></p>
 
             <label className='report-dialog-modal__toggle'>
               <Toggle checked={forward} disabled={isSubmitting} onChange={this.handleForwardChange} />
               <FormattedMessage id='report.forward' defaultMessage='Forward to {target}' values={{ target: domain }} />
             </label>
-          </React.Fragment>
+          </Fragment>
         )}
 
         <div className='flex-spacer' />
@@ -75,7 +75,7 @@ class Comment extends React.PureComponent {
         <div className='report-dialog-modal__actions'>
           <Button onClick={this.handleClick} disabled={isSubmitting}><FormattedMessage id='report.submit' defaultMessage='Submit report' /></Button>
         </div>
-      </React.Fragment>
+      </Fragment>
     );
   }
 
diff --git a/app/javascript/mastodon/features/report/components/option.jsx b/app/javascript/mastodon/features/report/components/option.jsx
index 34df4d73b3..9018d4775e 100644
--- a/app/javascript/mastodon/features/report/components/option.jsx
+++ b/app/javascript/mastodon/features/report/components/option.jsx
@@ -1,9 +1,9 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import { Check } from 'mastodon/components/check';
 
-export default class Option extends React.PureComponent {
+export default class Option extends PureComponent {
 
   static propTypes = {
     name: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/report/components/status_check_box.jsx b/app/javascript/mastodon/features/report/components/status_check_box.jsx
index 8d6091f778..e4b1333f80 100644
--- a/app/javascript/mastodon/features/report/components/status_check_box.jsx
+++ b/app/javascript/mastodon/features/report/components/status_check_box.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import StatusContent from 'mastodon/components/status_content';
@@ -17,7 +17,7 @@ const messages = defineMessages({
   direct_short: { id: 'privacy.direct.short', defaultMessage: 'Mentioned people only' },
 });
 
-class StatusCheckBox extends React.PureComponent {
+class StatusCheckBox extends PureComponent {
 
   static propTypes = {
     id: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/report/rules.jsx b/app/javascript/mastodon/features/report/rules.jsx
index b500c0503d..b6bb1fda63 100644
--- a/app/javascript/mastodon/features/report/rules.jsx
+++ b/app/javascript/mastodon/features/report/rules.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { connect } from 'react-redux';
@@ -10,7 +10,7 @@ const mapStateToProps = state => ({
   rules: state.getIn(['server', 'server', 'rules']),
 });
 
-class Rules extends React.PureComponent {
+class Rules extends PureComponent {
 
   static propTypes = {
     onNextStep: PropTypes.func.isRequired,
@@ -33,7 +33,7 @@ class Rules extends React.PureComponent {
     const { rules, selectedRuleIds } = this.props;
 
     return (
-      <React.Fragment>
+      <Fragment>
         <h3 className='report-dialog-modal__title'><FormattedMessage id='report.rules.title' defaultMessage='Which rules are being violated?' /></h3>
         <p className='report-dialog-modal__lead'><FormattedMessage id='report.rules.subtitle' defaultMessage='Select all that apply' /></p>
 
@@ -56,7 +56,7 @@ class Rules extends React.PureComponent {
         <div className='report-dialog-modal__actions'>
           <Button onClick={this.handleNextClick} disabled={selectedRuleIds.size < 1}><FormattedMessage id='report.next' defaultMessage='Next' /></Button>
         </div>
-      </React.Fragment>
+      </Fragment>
     );
   }
 
diff --git a/app/javascript/mastodon/features/report/statuses.jsx b/app/javascript/mastodon/features/report/statuses.jsx
index 87163aeb89..2a2435c58f 100644
--- a/app/javascript/mastodon/features/report/statuses.jsx
+++ b/app/javascript/mastodon/features/report/statuses.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { connect } from 'react-redux';
@@ -13,7 +13,7 @@ const mapStateToProps = (state, { accountId }) => ({
   isLoading: state.getIn(['timelines', `account:${accountId}:with_replies`, 'isLoading']),
 });
 
-class Statuses extends React.PureComponent {
+class Statuses extends PureComponent {
 
   static propTypes = {
     onNextStep: PropTypes.func.isRequired,
@@ -33,7 +33,7 @@ class Statuses extends React.PureComponent {
     const { availableStatusIds, selectedStatusIds, onToggle, isLoading } = this.props;
 
     return (
-      <React.Fragment>
+      <Fragment>
         <h3 className='report-dialog-modal__title'><FormattedMessage id='report.statuses.title' defaultMessage='Are there any posts that back up this report?' /></h3>
         <p className='report-dialog-modal__lead'><FormattedMessage id='report.statuses.subtitle' defaultMessage='Select all that apply' /></p>
 
@@ -53,7 +53,7 @@ class Statuses extends React.PureComponent {
         <div className='report-dialog-modal__actions'>
           <Button onClick={this.handleNextClick}><FormattedMessage id='report.next' defaultMessage='Next' /></Button>
         </div>
-      </React.Fragment>
+      </Fragment>
     );
   }
 
diff --git a/app/javascript/mastodon/features/report/thanks.jsx b/app/javascript/mastodon/features/report/thanks.jsx
index 4e5b6e8648..3f8765efde 100644
--- a/app/javascript/mastodon/features/report/thanks.jsx
+++ b/app/javascript/mastodon/features/report/thanks.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { FormattedMessage } from 'react-intl';
@@ -12,7 +12,7 @@ import {
 
 const mapStateToProps = () => ({});
 
-class Thanks extends React.PureComponent {
+class Thanks extends PureComponent {
 
   static propTypes = {
     submitted: PropTypes.bool,
@@ -48,17 +48,17 @@ class Thanks extends React.PureComponent {
     const { account, submitted } = this.props;
 
     return (
-      <React.Fragment>
+      <Fragment>
         <h3 className='report-dialog-modal__title'>{submitted ? <FormattedMessage id='report.thanks.title_actionable' defaultMessage="Thanks for reporting, we'll look into this." /> : <FormattedMessage id='report.thanks.title' defaultMessage="Don't want to see this?" />}</h3>
         <p className='report-dialog-modal__lead'>{submitted ? <FormattedMessage id='report.thanks.take_action_actionable' defaultMessage='While we review this, you can take action against @{name}:' values={{ name: account.get('username') }} /> : <FormattedMessage id='report.thanks.take_action' defaultMessage='Here are your options for controlling what you see on Mastodon:' />}</p>
 
         {account.getIn(['relationship', 'following']) && (
-          <React.Fragment>
+          <Fragment>
             <h4 className='report-dialog-modal__subtitle'><FormattedMessage id='report.unfollow' defaultMessage='Unfollow @{name}' values={{ name: account.get('username') }} /></h4>
             <p className='report-dialog-modal__lead'><FormattedMessage id='report.unfollow_explanation' defaultMessage='You are following this account. To not see their posts in your home feed anymore, unfollow them.' /></p>
             <Button secondary onClick={this.handleUnfollowClick}><FormattedMessage id='account.unfollow' defaultMessage='Unfollow' /></Button>
             <hr />
-          </React.Fragment>
+          </Fragment>
         )}
 
         <h4 className='report-dialog-modal__subtitle'><FormattedMessage id='account.mute' defaultMessage='Mute @{name}' values={{ name: account.get('username') }} /></h4>
@@ -76,7 +76,7 @@ class Thanks extends React.PureComponent {
         <div className='report-dialog-modal__actions'>
           <Button onClick={this.handleCloseClick}><FormattedMessage id='report.close' defaultMessage='Done' /></Button>
         </div>
-      </React.Fragment>
+      </Fragment>
     );
   }
 
diff --git a/app/javascript/mastodon/features/standalone/compose/index.jsx b/app/javascript/mastodon/features/standalone/compose/index.jsx
index fbadef6f4e..ae639bc1c3 100644
--- a/app/javascript/mastodon/features/standalone/compose/index.jsx
+++ b/app/javascript/mastodon/features/standalone/compose/index.jsx
@@ -1,10 +1,10 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import ComposeFormContainer from '../../compose/containers/compose_form_container';
 import NotificationsContainer from '../../ui/containers/notifications_container';
 import LoadingBarContainer from '../../ui/containers/loading_bar_container';
 import ModalContainer from '../../ui/containers/modal_container';
 
-export default class Compose extends React.PureComponent {
+export default class Compose extends PureComponent {
 
   render () {
     return (
diff --git a/app/javascript/mastodon/features/status/components/action_bar.jsx b/app/javascript/mastodon/features/status/components/action_bar.jsx
index e5b08ff285..cd721cb137 100644
--- a/app/javascript/mastodon/features/status/components/action_bar.jsx
+++ b/app/javascript/mastodon/features/status/components/action_bar.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { connect } from 'react-redux';
 import { IconButton } from '../../../components/icon_button';
@@ -47,7 +47,7 @@ const mapStateToProps = (state, { status }) => ({
   relationship: state.getIn(['relationships', status.getIn(['account', 'id'])]),
 });
 
-class ActionBar extends React.PureComponent {
+class ActionBar extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object,
diff --git a/app/javascript/mastodon/features/status/components/card.jsx b/app/javascript/mastodon/features/status/components/card.jsx
index bc02665311..6634d2c71f 100644
--- a/app/javascript/mastodon/features/status/components/card.jsx
+++ b/app/javascript/mastodon/features/status/components/card.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import Immutable from 'immutable';
 import ImmutablePropTypes from 'react-immutable-proptypes';
@@ -47,7 +47,7 @@ const addAutoPlay = html => {
   return html;
 };
 
-export default class Card extends React.PureComponent {
+export default class Card extends PureComponent {
 
   static propTypes = {
     card: ImmutablePropTypes.map,
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.jsx b/app/javascript/mastodon/features/status/components/detailed_status.jsx
index 5019dfdb4d..f371868e7e 100644
--- a/app/javascript/mastodon/features/status/components/detailed_status.jsx
+++ b/app/javascript/mastodon/features/status/components/detailed_status.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { Fragment } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { Avatar } from '../../../components/avatar';
@@ -190,7 +190,7 @@ class DetailedStatus extends ImmutablePureComponent {
     }
 
     if (status.get('application')) {
-      applicationLink = <React.Fragment> · <a className='detailed-status__application' href={status.getIn(['application', 'website'])} target='_blank' rel='noopener noreferrer'>{status.getIn(['application', 'name'])}</a></React.Fragment>;
+      applicationLink = <Fragment> · <a className='detailed-status__application' href={status.getIn(['application', 'website'])} target='_blank' rel='noopener noreferrer'>{status.getIn(['application', 'name'])}</a></Fragment>;
     }
 
     const visibilityIconInfo = {
@@ -201,33 +201,33 @@ class DetailedStatus extends ImmutablePureComponent {
     };
 
     const visibilityIcon = visibilityIconInfo[status.get('visibility')];
-    const visibilityLink = <React.Fragment> · <Icon id={visibilityIcon.icon} title={visibilityIcon.text} /></React.Fragment>;
+    const visibilityLink = <Fragment> · <Icon id={visibilityIcon.icon} title={visibilityIcon.text} /></Fragment>;
 
     if (['private', 'direct'].includes(status.get('visibility'))) {
       reblogLink = '';
     } else if (this.context.router) {
       reblogLink = (
-        <React.Fragment>
-          <React.Fragment> · </React.Fragment>
+        <Fragment>
+          <Fragment> · </Fragment>
           <Link to={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}/reblogs`} className='detailed-status__link'>
             <Icon id={reblogIcon} />
             <span className='detailed-status__reblogs'>
               <AnimatedNumber value={status.get('reblogs_count')} />
             </span>
           </Link>
-        </React.Fragment>
+        </Fragment>
       );
     } else {
       reblogLink = (
-        <React.Fragment>
-          <React.Fragment> · </React.Fragment>
+        <Fragment>
+          <Fragment> · </Fragment>
           <a href={`/interact/${status.get('id')}?type=reblog`} className='detailed-status__link' onClick={this.handleModalLink}>
             <Icon id={reblogIcon} />
             <span className='detailed-status__reblogs'>
               <AnimatedNumber value={status.get('reblogs_count')} />
             </span>
           </a>
-        </React.Fragment>
+        </Fragment>
       );
     }
 
@@ -253,10 +253,10 @@ class DetailedStatus extends ImmutablePureComponent {
 
     if (status.get('edited_at')) {
       edited = (
-        <React.Fragment>
-          <React.Fragment> · </React.Fragment>
+        <Fragment>
+          <Fragment> · </Fragment>
           <EditedTimestamp statusId={status.get('id')} timestamp={status.get('edited_at')} />
-        </React.Fragment>
+        </Fragment>
       );
     }
 
diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx
index 5f1715c27e..3570e0f35a 100644
--- a/app/javascript/mastodon/features/status/index.jsx
+++ b/app/javascript/mastodon/features/status/index.jsx
@@ -1,5 +1,4 @@
 import Immutable from 'immutable';
-import React from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
diff --git a/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx b/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx
index a9dd1e0720..6ef6ce86af 100644
--- a/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx
+++ b/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import ImmutablePropTypes from 'react-immutable-proptypes';
diff --git a/app/javascript/mastodon/features/ui/components/__tests__/column-test.jsx b/app/javascript/mastodon/features/ui/components/__tests__/column-test.jsx
index a56859be07..8f935299fa 100644
--- a/app/javascript/mastodon/features/ui/components/__tests__/column-test.jsx
+++ b/app/javascript/mastodon/features/ui/components/__tests__/column-test.jsx
@@ -1,5 +1,4 @@
 import { render, fireEvent, screen } from '@testing-library/react';
-import React from 'react';
 import Column from '../column';
 
 describe('<Column />', () => {
diff --git a/app/javascript/mastodon/features/ui/components/actions_modal.jsx b/app/javascript/mastodon/features/ui/components/actions_modal.jsx
index 9d11da6085..d8d9ef9637 100644
--- a/app/javascript/mastodon/features/ui/components/actions_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/actions_modal.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
diff --git a/app/javascript/mastodon/features/ui/components/audio_modal.jsx b/app/javascript/mastodon/features/ui/components/audio_modal.jsx
index c0ac12ba7b..a1dbe9b730 100644
--- a/app/javascript/mastodon/features/ui/components/audio_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/audio_modal.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import Audio from 'mastodon/features/audio';
diff --git a/app/javascript/mastodon/features/ui/components/block_modal.jsx b/app/javascript/mastodon/features/ui/components/block_modal.jsx
index a9506aa69f..3e3f7c83ac 100644
--- a/app/javascript/mastodon/features/ui/components/block_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/block_modal.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import { injectIntl, FormattedMessage } from 'react-intl';
@@ -36,7 +36,7 @@ const mapDispatchToProps = dispatch => {
   };
 };
 
-class BlockModal extends React.PureComponent {
+class BlockModal extends PureComponent {
 
   static propTypes = {
     account: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/boost_modal.jsx b/app/javascript/mastodon/features/ui/components/boost_modal.jsx
index 4eeb30be09..d20cd255b0 100644
--- a/app/javascript/mastodon/features/ui/components/boost_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/boost_modal.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/ui/components/bundle.jsx b/app/javascript/mastodon/features/ui/components/bundle.jsx
index c1e837b16e..1474d89a44 100644
--- a/app/javascript/mastodon/features/ui/components/bundle.jsx
+++ b/app/javascript/mastodon/features/ui/components/bundle.jsx
@@ -1,10 +1,10 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 
 const emptyComponent = () => null;
 const noop = () => { };
 
-class Bundle extends React.PureComponent {
+class Bundle extends PureComponent {
 
   static propTypes = {
     fetchComponent: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/bundle_column_error.jsx b/app/javascript/mastodon/features/ui/components/bundle_column_error.jsx
index dc9b0e5392..f92b44f5d1 100644
--- a/app/javascript/mastodon/features/ui/components/bundle_column_error.jsx
+++ b/app/javascript/mastodon/features/ui/components/bundle_column_error.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { injectIntl, FormattedMessage } from 'react-intl';
 import Column from 'mastodon/components/column';
@@ -8,7 +8,7 @@ import { Link } from 'react-router-dom';
 import classNames from 'classnames';
 import { autoPlayGif } from 'mastodon/initial_state';
 
-class GIF extends React.PureComponent {
+class GIF extends PureComponent {
 
   static propTypes = {
     src: PropTypes.string.isRequired,
@@ -59,7 +59,7 @@ class GIF extends React.PureComponent {
 
 }
 
-class CopyButton extends React.PureComponent {
+class CopyButton extends PureComponent {
 
   static propTypes = {
     children: PropTypes.node.isRequired,
@@ -92,7 +92,7 @@ class CopyButton extends React.PureComponent {
 
 }
 
-class BundleColumnError extends React.PureComponent {
+class BundleColumnError extends PureComponent {
 
   static propTypes = {
     errorType: PropTypes.oneOf(['routing', 'network', 'error']),
diff --git a/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx b/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx
index 6ddf2ae7ac..e39b8c4b25 100644
--- a/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx
+++ b/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl } from 'react-intl';
 
@@ -10,7 +10,7 @@ const messages = defineMessages({
   close: { id: 'bundle_modal_error.close', defaultMessage: 'Close' },
 });
 
-class BundleModalError extends React.PureComponent {
+class BundleModalError extends PureComponent {
 
   static propTypes = {
     onRetry: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/column.jsx b/app/javascript/mastodon/features/ui/components/column.jsx
index 7bc2f7e00a..69bf7ca4d6 100644
--- a/app/javascript/mastodon/features/ui/components/column.jsx
+++ b/app/javascript/mastodon/features/ui/components/column.jsx
@@ -1,11 +1,11 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import ColumnHeader from './column_header';
 import PropTypes from 'prop-types';
 import { debounce } from 'lodash';
 import { scrollTop } from '../../../scroll';
 import { isMobile } from '../../../is_mobile';
 
-export default class Column extends React.PureComponent {
+export default class Column extends PureComponent {
 
   static propTypes = {
     heading: PropTypes.string,
diff --git a/app/javascript/mastodon/features/ui/components/column_header.jsx b/app/javascript/mastodon/features/ui/components/column_header.jsx
index a2d3a38710..b1ac14338f 100644
--- a/app/javascript/mastodon/features/ui/components/column_header.jsx
+++ b/app/javascript/mastodon/features/ui/components/column_header.jsx
@@ -1,9 +1,9 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import { Icon }  from 'mastodon/components/icon';
 
-export default class ColumnHeader extends React.PureComponent {
+export default class ColumnHeader extends PureComponent {
 
   static propTypes = {
     icon: PropTypes.string,
diff --git a/app/javascript/mastodon/features/ui/components/column_link.jsx b/app/javascript/mastodon/features/ui/components/column_link.jsx
index 4e9164afb7..434244fbdc 100644
--- a/app/javascript/mastodon/features/ui/components/column_link.jsx
+++ b/app/javascript/mastodon/features/ui/components/column_link.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import { NavLink } from 'react-router-dom';
 import { Icon }  from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/ui/components/column_loading.jsx b/app/javascript/mastodon/features/ui/components/column_loading.jsx
index e5ed225844..72cc68e824 100644
--- a/app/javascript/mastodon/features/ui/components/column_loading.jsx
+++ b/app/javascript/mastodon/features/ui/components/column_loading.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 
 import Column from '../../../components/column';
diff --git a/app/javascript/mastodon/features/ui/components/column_subheading.jsx b/app/javascript/mastodon/features/ui/components/column_subheading.jsx
index 8160c4aa39..e970a0bfdd 100644
--- a/app/javascript/mastodon/features/ui/components/column_subheading.jsx
+++ b/app/javascript/mastodon/features/ui/components/column_subheading.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 
 const ColumnSubheading = ({ text }) => {
diff --git a/app/javascript/mastodon/features/ui/components/columns_area.jsx b/app/javascript/mastodon/features/ui/components/columns_area.jsx
index 86911efa38..07913646f5 100644
--- a/app/javascript/mastodon/features/ui/components/columns_area.jsx
+++ b/app/javascript/mastodon/features/ui/components/columns_area.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { Children, cloneElement } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
@@ -173,7 +173,7 @@ export default class ColumnsArea extends ImmutablePureComponent {
           );
         })}
 
-        {React.Children.map(children, child => React.cloneElement(child, { multiColumn: true }))}
+        {Children.map(children, child => cloneElement(child, { multiColumn: true }))}
       </div>
     );
   }
diff --git a/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx b/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
index 8e4c4d1368..a6fcde8769 100644
--- a/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import { connect } from 'react-redux';
@@ -24,7 +24,7 @@ const mapDispatchToProps = dispatch => ({
 
 });
 
-class CompareHistoryModal extends React.PureComponent {
+class CompareHistoryModal extends PureComponent {
 
   static propTypes = {
     onClose: PropTypes.func.isRequired,
@@ -65,10 +65,10 @@ class CompareHistoryModal extends React.PureComponent {
         <div className='compare-history-modal__container'>
           <div className='status__content'>
             {currentVersion.get('spoiler_text').length > 0 && (
-              <React.Fragment>
+              <Fragment>
                 <div className='translate' dangerouslySetInnerHTML={spoilerContent} lang={language} />
                 <hr />
-              </React.Fragment>
+              </Fragment>
             )}
 
             <div className='status__content__text status__content__text--visible translate' dangerouslySetInnerHTML={content} lang={language} />
diff --git a/app/javascript/mastodon/features/ui/components/compose_panel.jsx b/app/javascript/mastodon/features/ui/components/compose_panel.jsx
index 1c6f80ad5c..f81072fcb4 100644
--- a/app/javascript/mastodon/features/ui/components/compose_panel.jsx
+++ b/app/javascript/mastodon/features/ui/components/compose_panel.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import SearchContainer from 'mastodon/features/compose/containers/search_container';
@@ -8,7 +8,7 @@ import LinkFooter from './link_footer';
 import ServerBanner from 'mastodon/components/server_banner';
 import { changeComposing, mountCompose, unmountCompose } from 'mastodon/actions/compose';
 
-class ComposePanel extends React.PureComponent {
+class ComposePanel extends PureComponent {
 
   static contextTypes = {
     identity: PropTypes.object.isRequired,
@@ -46,17 +46,17 @@ class ComposePanel extends React.PureComponent {
         <SearchContainer openInRoute />
 
         {!signedIn && (
-          <React.Fragment>
+          <Fragment>
             <ServerBanner />
             <div className='flex-spacer' />
-          </React.Fragment>
+          </Fragment>
         )}
 
         {signedIn && (
-          <React.Fragment>
+          <Fragment>
             <NavigationContainer onClose={this.onBlur} />
             <ComposeFormContainer singleColumn />
-          </React.Fragment>
+          </Fragment>
         )}
 
         <LinkFooter />
diff --git a/app/javascript/mastodon/features/ui/components/confirmation_modal.jsx b/app/javascript/mastodon/features/ui/components/confirmation_modal.jsx
index 4437567a14..412993ea2c 100644
--- a/app/javascript/mastodon/features/ui/components/confirmation_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/confirmation_modal.jsx
@@ -1,9 +1,9 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { injectIntl, FormattedMessage } from 'react-intl';
 import Button from '../../../components/button';
 
-class ConfirmationModal extends React.PureComponent {
+class ConfirmationModal extends PureComponent {
 
   static propTypes = {
     message: PropTypes.node.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/disabled_account_banner.jsx b/app/javascript/mastodon/features/ui/components/disabled_account_banner.jsx
index ea11cea44d..0fa497e8bf 100644
--- a/app/javascript/mastodon/features/ui/components/disabled_account_banner.jsx
+++ b/app/javascript/mastodon/features/ui/components/disabled_account_banner.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { connect } from 'react-redux';
 import { Link } from 'react-router-dom';
@@ -28,7 +28,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
   },
 });
 
-class DisabledAccountBanner extends React.PureComponent {
+class DisabledAccountBanner extends PureComponent {
 
   static propTypes = {
     disabledAcct: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/drawer_loading.jsx b/app/javascript/mastodon/features/ui/components/drawer_loading.jsx
index 08b0d23476..11072ad98c 100644
--- a/app/javascript/mastodon/features/ui/components/drawer_loading.jsx
+++ b/app/javascript/mastodon/features/ui/components/drawer_loading.jsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 const DrawerLoading = () => (
   <div className='drawer'>
     <div className='drawer__pager'>
diff --git a/app/javascript/mastodon/features/ui/components/embed_modal.jsx b/app/javascript/mastodon/features/ui/components/embed_modal.jsx
index 949c640421..6187bfeb20 100644
--- a/app/javascript/mastodon/features/ui/components/embed_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/embed_modal.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
diff --git a/app/javascript/mastodon/features/ui/components/filter_modal.jsx b/app/javascript/mastodon/features/ui/components/filter_modal.jsx
index 473fe4b360..7b5a1a03a6 100644
--- a/app/javascript/mastodon/features/ui/components/filter_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/filter_modal.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { fetchStatus } from 'mastodon/actions/statuses';
 import { fetchFilters, createFilter, createFilterStatus } from 'mastodon/actions/filters';
diff --git a/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx b/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
index d6f15e276b..5c831d65b0 100644
--- a/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import ImmutablePureComponent from 'react-immutable-pure-component';
@@ -69,7 +69,7 @@ const removeExtraLineBreaks = str => str.replace(/\n\n/g, '******')
   .replace(/\n/g, ' ')
   .replace(/\*\*\*\*\*\*/g, '\n\n');
 
-class ImageLoader extends React.PureComponent {
+class ImageLoader extends PureComponent {
 
   static propTypes = {
     src: PropTypes.string.isRequired,
@@ -315,7 +315,7 @@ class FocalPointModal extends ImmutablePureComponent {
             {focals && <p><FormattedMessage id='upload_modal.hint' defaultMessage='Click or drag the circle on the preview to choose the focal point which will always be in view on all thumbnails.' /></p>}
 
             {thumbnailable && (
-              <React.Fragment>
+              <Fragment>
                 <label className='setting-text-label' htmlFor='upload-modal__thumbnail'><FormattedMessage id='upload_form.thumbnail' defaultMessage='Change thumbnail' /></label>
 
                 <Button disabled={isUploadingThumbnail || !media.get('unattached')} text={intl.formatMessage(messages.chooseImage)} onClick={this.handleFileInputClick} />
@@ -335,7 +335,7 @@ class FocalPointModal extends ImmutablePureComponent {
                 </label>
 
                 <hr className='setting-divider' />
-              </React.Fragment>
+              </Fragment>
             )}
 
             <label className='setting-text-label' htmlFor='upload-modal__description'>
diff --git a/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx b/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx
index 9c8ebd13cd..fcc2e180a0 100644
--- a/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx
+++ b/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { Component } from 'react';
 import PropTypes from 'prop-types';
 import { fetchFollowRequests } from 'mastodon/actions/accounts';
 import { connect } from 'react-redux';
@@ -15,7 +15,7 @@ const mapStateToProps = state => ({
   count: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
 });
 
-class FollowRequestsColumnLink extends React.Component {
+class FollowRequestsColumnLink extends Component {
 
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/header.jsx b/app/javascript/mastodon/features/ui/components/header.jsx
index 6419dbc50d..79b43ecb60 100644
--- a/app/javascript/mastodon/features/ui/components/header.jsx
+++ b/app/javascript/mastodon/features/ui/components/header.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { WordmarkLogo, SymbolLogo } from 'mastodon/components/logo';
 import { Link, withRouter } from 'react-router-dom';
 import { FormattedMessage } from 'react-intl';
@@ -22,7 +22,7 @@ const mapDispatchToProps = (dispatch) => ({
   },
 });
 
-class Header extends React.PureComponent {
+class Header extends PureComponent {
 
   static contextTypes = {
     identity: PropTypes.object,
diff --git a/app/javascript/mastodon/features/ui/components/image_loader.jsx b/app/javascript/mastodon/features/ui/components/image_loader.jsx
index 9093eab28e..62b54a3e97 100644
--- a/app/javascript/mastodon/features/ui/components/image_loader.jsx
+++ b/app/javascript/mastodon/features/ui/components/image_loader.jsx
@@ -1,6 +1,6 @@
 import classNames from 'classnames';
 import PropTypes from 'prop-types';
-import React, { PureComponent } from 'react';
+import { PureComponent } from 'react';
 import { LoadingBar } from 'react-redux-loading-bar';
 import ZoomableImage from './zoomable_image';
 
diff --git a/app/javascript/mastodon/features/ui/components/image_modal.jsx b/app/javascript/mastodon/features/ui/components/image_modal.jsx
index 31c5ab37ad..a55095dc0f 100644
--- a/app/javascript/mastodon/features/ui/components/image_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/image_modal.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import classNames from 'classnames';
 import { defineMessages, injectIntl } from 'react-intl';
@@ -9,7 +9,7 @@ const messages = defineMessages({
   close: { id: 'lightbox.close', defaultMessage: 'Close' },
 });
 
-class ImageModal extends React.PureComponent {
+class ImageModal extends PureComponent {
 
   static propTypes = {
     src: PropTypes.string.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/link_footer.jsx b/app/javascript/mastodon/features/ui/components/link_footer.jsx
index 68ef015ab9..273b089bb2 100644
--- a/app/javascript/mastodon/features/ui/components/link_footer.jsx
+++ b/app/javascript/mastodon/features/ui/components/link_footer.jsx
@@ -1,5 +1,5 @@
 import { connect } from 'react-redux';
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
 import { Link } from 'react-router-dom';
@@ -24,7 +24,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
   },
 });
 
-class LinkFooter extends React.PureComponent {
+class LinkFooter extends PureComponent {
 
   static contextTypes = {
     identity: PropTypes.object,
diff --git a/app/javascript/mastodon/features/ui/components/list_panel.jsx b/app/javascript/mastodon/features/ui/components/list_panel.jsx
index fcff4e37dc..70e84e9b62 100644
--- a/app/javascript/mastodon/features/ui/components/list_panel.jsx
+++ b/app/javascript/mastodon/features/ui/components/list_panel.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import PropTypes from 'prop-types';
 import { createSelector } from 'reselect';
 import ImmutablePropTypes from 'react-immutable-proptypes';
diff --git a/app/javascript/mastodon/features/ui/components/media_modal.jsx b/app/javascript/mastodon/features/ui/components/media_modal.jsx
index 594f5cf64f..1c9cf19e09 100644
--- a/app/javascript/mastodon/features/ui/components/media_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/media_modal.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ReactSwipeableViews from 'react-swipeable-views';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/ui/components/modal_loading.jsx b/app/javascript/mastodon/features/ui/components/modal_loading.jsx
index f403ca4c9e..7a6bbf5fa2 100644
--- a/app/javascript/mastodon/features/ui/components/modal_loading.jsx
+++ b/app/javascript/mastodon/features/ui/components/modal_loading.jsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 import LoadingIndicator from '../../../components/loading_indicator';
 
 // Keep the markup in sync with <BundleModalError />
diff --git a/app/javascript/mastodon/features/ui/components/modal_root.jsx b/app/javascript/mastodon/features/ui/components/modal_root.jsx
index c252e6caac..c86b5726d4 100644
--- a/app/javascript/mastodon/features/ui/components/modal_root.jsx
+++ b/app/javascript/mastodon/features/ui/components/modal_root.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { getScrollbarWidth } from 'mastodon/utils/scrollbar';
 import Base from 'mastodon/components/modal_root';
@@ -50,7 +50,7 @@ const MODAL_COMPONENTS = {
   'CLOSED_REGISTRATIONS': ClosedRegistrationsModal,
 };
 
-export default class ModalRoot extends React.PureComponent {
+export default class ModalRoot extends PureComponent {
 
   static propTypes = {
     type: PropTypes.string,
diff --git a/app/javascript/mastodon/features/ui/components/mute_modal.jsx b/app/javascript/mastodon/features/ui/components/mute_modal.jsx
index fa64bf0f40..f43a9b8ede 100644
--- a/app/javascript/mastodon/features/ui/components/mute_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/mute_modal.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
@@ -43,7 +43,7 @@ const mapDispatchToProps = dispatch => {
   };
 };
 
-class MuteModal extends React.PureComponent {
+class MuteModal extends PureComponent {
 
   static propTypes = {
     account: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
index b62d216ae9..025c3b8a5b 100644
--- a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
+++ b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { Component, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl } from 'react-intl';
 import { Link } from 'react-router-dom';
@@ -28,7 +28,7 @@ const messages = defineMessages({
   search: { id: 'navigation_bar.search', defaultMessage: 'Search' },
 });
 
-class NavigationPanel extends React.Component {
+class NavigationPanel extends Component {
 
   static contextTypes = {
     router: PropTypes.object.isRequired,
@@ -51,11 +51,11 @@ class NavigationPanel extends React.Component {
         </div>
 
         {signedIn && (
-          <React.Fragment>
+          <Fragment>
             <ColumnLink transparent to='/home' icon='home' text={intl.formatMessage(messages.home)} />
             <ColumnLink transparent to='/notifications' icon={<NotificationsCounterIcon className='column-link__icon' />} text={intl.formatMessage(messages.notifications)} />
             <FollowRequestsColumnLink />
-          </React.Fragment>
+          </Fragment>
         )}
 
         {showTrends ? (
@@ -79,7 +79,7 @@ class NavigationPanel extends React.Component {
         )}
 
         {signedIn && (
-          <React.Fragment>
+          <Fragment>
             <ColumnLink transparent to='/conversations' icon='at' text={intl.formatMessage(messages.direct)} />
             <ColumnLink transparent to='/bookmarks' icon='bookmark' text={intl.formatMessage(messages.bookmarks)} />
             <ColumnLink transparent to='/favourites' icon='star' text={intl.formatMessage(messages.favourites)} />
@@ -90,7 +90,7 @@ class NavigationPanel extends React.Component {
             <hr />
 
             <ColumnLink transparent href='/settings/preferences' icon='cog' text={intl.formatMessage(messages.preferences)} />
-          </React.Fragment>
+          </Fragment>
         )}
 
         <div className='navigation-panel__legal'>
diff --git a/app/javascript/mastodon/features/ui/components/report_modal.jsx b/app/javascript/mastodon/features/ui/components/report_modal.jsx
index f3ada9c07b..c7909040ed 100644
--- a/app/javascript/mastodon/features/ui/components/report_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/report_modal.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { connect } from 'react-redux';
 import { submitReport } from 'mastodon/actions/reports';
 import { expandAccountTimeline } from 'mastodon/actions/timelines';
diff --git a/app/javascript/mastodon/features/ui/components/sign_in_banner.jsx b/app/javascript/mastodon/features/ui/components/sign_in_banner.jsx
index 39f0c71c34..984a574e56 100644
--- a/app/javascript/mastodon/features/ui/components/sign_in_banner.jsx
+++ b/app/javascript/mastodon/features/ui/components/sign_in_banner.jsx
@@ -1,4 +1,4 @@
-import React, { useCallback } from 'react';
+import { useCallback } from 'react';
 import { FormattedMessage } from 'react-intl';
 import { useDispatch } from 'react-redux';
 import { registrationsOpen } from 'mastodon/initial_state';
diff --git a/app/javascript/mastodon/features/ui/components/upload_area.jsx b/app/javascript/mastodon/features/ui/components/upload_area.jsx
index cec4cf5b1e..64df8fbf7d 100644
--- a/app/javascript/mastodon/features/ui/components/upload_area.jsx
+++ b/app/javascript/mastodon/features/ui/components/upload_area.jsx
@@ -1,10 +1,10 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import Motion from '../util/optional_motion';
 import spring from 'react-motion/lib/spring';
 import { FormattedMessage } from 'react-intl';
 
-export default class UploadArea extends React.PureComponent {
+export default class UploadArea extends PureComponent {
 
   static propTypes = {
     active: PropTypes.bool,
diff --git a/app/javascript/mastodon/features/ui/components/video_modal.jsx b/app/javascript/mastodon/features/ui/components/video_modal.jsx
index 99359a58cc..ffc863530d 100644
--- a/app/javascript/mastodon/features/ui/components/video_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/video_modal.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import PropTypes from 'prop-types';
 import Video from 'mastodon/features/video';
diff --git a/app/javascript/mastodon/features/ui/components/zoomable_image.jsx b/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
index 49be6d5c3b..8c2e6e2cc3 100644
--- a/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
+++ b/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent, Fragment } from 'react';
 import PropTypes from 'prop-types';
 import { IconButton } from 'mastodon/components/icon_button';
 import { defineMessages, injectIntl } from 'react-intl';
@@ -91,7 +91,7 @@ const normalizeWheel = event => {
   };
 };
 
-class ZoomableImage extends React.PureComponent {
+class ZoomableImage extends PureComponent {
 
   static propTypes = {
     alt: PropTypes.string,
@@ -411,7 +411,7 @@ class ZoomableImage extends React.PureComponent {
     const zoomButtonTitle = this.state.zoomState === 'compress' ? intl.formatMessage(messages.compress) : intl.formatMessage(messages.expand);
 
     return (
-      <React.Fragment>
+      <Fragment>
         <IconButton
           className={`media-modal__zoom-button ${zoomButtonShouldHide}`}
           title={zoomButtonTitle}
@@ -445,7 +445,7 @@ class ZoomableImage extends React.PureComponent {
             onMouseDown={this.handleMouseDown}
           />
         </div>
-      </React.Fragment>
+      </Fragment>
     );
   }
 
diff --git a/app/javascript/mastodon/features/ui/index.jsx b/app/javascript/mastodon/features/ui/index.jsx
index 26a7777324..09b30d4d70 100644
--- a/app/javascript/mastodon/features/ui/index.jsx
+++ b/app/javascript/mastodon/features/ui/index.jsx
@@ -1,5 +1,5 @@
 import classNames from 'classnames';
-import React from 'react';
+import { PureComponent } from 'react';
 import { HotKeys } from 'react-hotkeys';
 import { defineMessages, injectIntl } from 'react-intl';
 import { connect } from 'react-redux';
@@ -111,7 +111,7 @@ const keyMap = {
   openMedia: 'e',
 };
 
-class SwitchingColumnsArea extends React.PureComponent {
+class SwitchingColumnsArea extends PureComponent {
 
   static contextTypes = {
     identity: PropTypes.object,
@@ -229,7 +229,7 @@ class SwitchingColumnsArea extends React.PureComponent {
 
 }
 
-class UI extends React.PureComponent {
+class UI extends PureComponent {
 
   static contextTypes = {
     router: PropTypes.object.isRequired,
diff --git a/app/javascript/mastodon/features/ui/util/react_router_helpers.jsx b/app/javascript/mastodon/features/ui/util/react_router_helpers.jsx
index 21b3528785..64aad000ac 100644
--- a/app/javascript/mastodon/features/ui/util/react_router_helpers.jsx
+++ b/app/javascript/mastodon/features/ui/util/react_router_helpers.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { Component, PureComponent, cloneElement, Children } from 'react';
 import PropTypes from 'prop-types';
 import { Switch, Route } from 'react-router-dom';
 import StackTrace from 'stacktrace-js';
@@ -7,14 +7,14 @@ import BundleColumnError from '../components/bundle_column_error';
 import BundleContainer from '../containers/bundle_container';
 
 // Small wrapper to pass multiColumn to the route components
-export class WrappedSwitch extends React.PureComponent {
+export class WrappedSwitch extends PureComponent {
 
   render () {
     const { multiColumn, children } = this.props;
 
     return (
       <Switch>
-        {React.Children.map(children, child => React.cloneElement(child, { multiColumn }))}
+        {Children.map(children, child => cloneElement(child, { multiColumn }))}
       </Switch>
     );
   }
@@ -29,7 +29,7 @@ WrappedSwitch.propTypes = {
 // Small Wrapper to extract the params from the route and pass
 // them to the rendered component, together with the content to
 // be rendered inside (the children)
-export class WrappedRoute extends React.Component {
+export class WrappedRoute extends Component {
 
   static propTypes = {
     component: PropTypes.func.isRequired,
diff --git a/app/javascript/mastodon/features/ui/util/reduced_motion.jsx b/app/javascript/mastodon/features/ui/util/reduced_motion.jsx
index 1123b80ed9..85ede744c8 100644
--- a/app/javascript/mastodon/features/ui/util/reduced_motion.jsx
+++ b/app/javascript/mastodon/features/ui/util/reduced_motion.jsx
@@ -1,6 +1,6 @@
 // Like react-motion's Motion, but reduces all animations to cross-fades
 // for the benefit of users with motion sickness.
-import React from 'react';
+import { Component } from 'react';
 import Motion from 'react-motion/lib/Motion';
 import PropTypes from 'prop-types';
 
@@ -11,7 +11,7 @@ const extractValue = (value) => {
   return (typeof value === 'object' && value && 'val' in value) ? value.val : value;
 };
 
-class ReducedMotion extends React.Component {
+class ReducedMotion extends Component {
 
   static propTypes = {
     defaultStyle: PropTypes.object,
diff --git a/app/javascript/mastodon/features/video/index.jsx b/app/javascript/mastodon/features/video/index.jsx
index 560dbc6d6a..81ed457c99 100644
--- a/app/javascript/mastodon/features/video/index.jsx
+++ b/app/javascript/mastodon/features/video/index.jsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import { PureComponent } from 'react';
 import PropTypes from 'prop-types';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import { is } from 'immutable';
@@ -94,7 +94,7 @@ export const fileNameFromURL = str => {
   return pathname.slice(index + 1);
 };
 
-class Video extends React.PureComponent {
+class Video extends PureComponent {
 
   static propTypes = {
     preview: PropTypes.string,
diff --git a/app/javascript/mastodon/main.jsx b/app/javascript/mastodon/main.jsx
index b31540cb55..8f45e18f72 100644
--- a/app/javascript/mastodon/main.jsx
+++ b/app/javascript/mastodon/main.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
 import { createRoot } from 'react-dom/client';
 import { setupBrowserNotifications } from 'mastodon/actions/notifications';
 import Mastodon from 'mastodon/containers/mastodon';
diff --git a/app/javascript/mastodon/utils/icons.jsx b/app/javascript/mastodon/utils/icons.jsx
index c3e362e39a..be566032e0 100644
--- a/app/javascript/mastodon/utils/icons.jsx
+++ b/app/javascript/mastodon/utils/icons.jsx
@@ -1,5 +1,3 @@
-import React from 'react';
-
 // Copied from emoji-mart for consistency with emoji picker and since
 // they don't export the icons in the package
 export const loupeIcon = (
diff --git a/babel.config.js b/babel.config.js
index abfdc5b2ca..0a2e69a476 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -3,6 +3,7 @@ module.exports = (api) => {
 
   const reactOptions = {
     development: false,
+    runtime: 'automatic',
   };
 
   const envOptions = {
diff --git a/tsconfig.json b/tsconfig.json
index 2c2193d55f..ff9da29497 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,6 @@
 {
   "compilerOptions": {
-    "jsx": "react",
+    "jsx": "react-jsx",
     "target": "esnext",
     "module": "CommonJS",
     "moduleResolution": "node",
-- 
GitLab