diff --git a/app/javascript/mastodon/components/dismissable_banner.jsx b/app/javascript/mastodon/components/dismissable_banner.jsx
deleted file mode 100644
index 5aecc88b1..000000000
--- a/app/javascript/mastodon/components/dismissable_banner.jsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import PropTypes from 'prop-types';
-import { PureComponent } from 'react';
-
-import { injectIntl, defineMessages } from 'react-intl';
-
-import { bannerSettings } from 'mastodon/settings';
-
-import { IconButton } from './icon_button';
-
-const messages = defineMessages({
- dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' },
-});
-
-class DismissableBanner extends PureComponent {
-
- static propTypes = {
- id: PropTypes.string.isRequired,
- children: PropTypes.node,
- intl: PropTypes.object.isRequired,
- };
-
- state = {
- visible: !bannerSettings.get(this.props.id),
- };
-
- handleDismiss = () => {
- const { id } = this.props;
- this.setState({ visible: false }, () => bannerSettings.set(id, true));
- };
-
- render () {
- const { visible } = this.state;
-
- if (!visible) {
- return null;
- }
-
- const { children, intl } = this.props;
-
- return (
-
-
- {children}
-
-
-
-
-
-
- );
- }
-
-}
-
-export default injectIntl(DismissableBanner);
diff --git a/app/javascript/mastodon/components/dismissable_banner.tsx b/app/javascript/mastodon/components/dismissable_banner.tsx
new file mode 100644
index 000000000..d5cdb0750
--- /dev/null
+++ b/app/javascript/mastodon/components/dismissable_banner.tsx
@@ -0,0 +1,47 @@
+import type { PropsWithChildren } from 'react';
+import { useCallback, useState } from 'react';
+
+import { defineMessages, useIntl } from 'react-intl';
+
+import { bannerSettings } from 'mastodon/settings';
+
+import { IconButton } from './icon_button';
+
+const messages = defineMessages({
+ dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' },
+});
+
+interface Props {
+ id: string;
+}
+
+export const DismissableBanner: React.FC> = ({
+ id,
+ children,
+}) => {
+ const [visible, setVisible] = useState(!bannerSettings.get(id));
+ const intl = useIntl();
+
+ const handleDismiss = useCallback(() => {
+ setVisible(false);
+ bannerSettings.set(id, true);
+ }, [id]);
+
+ if (!visible) {
+ return null;
+ }
+
+ return (
+
+ );
+};
diff --git a/app/javascript/mastodon/features/community_timeline/index.jsx b/app/javascript/mastodon/features/community_timeline/index.jsx
index 7e3b9babe..2d94cabed 100644
--- a/app/javascript/mastodon/features/community_timeline/index.jsx
+++ b/app/javascript/mastodon/features/community_timeline/index.jsx
@@ -7,7 +7,7 @@ import { Helmet } from 'react-helmet';
import { connect } from 'react-redux';
-import DismissableBanner from 'mastodon/components/dismissable_banner';
+import { DismissableBanner } from 'mastodon/components/dismissable_banner';
import { domain } from 'mastodon/initial_state';
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
diff --git a/app/javascript/mastodon/features/explore/links.jsx b/app/javascript/mastodon/features/explore/links.jsx
index 49c667f02..8b199bf47 100644
--- a/app/javascript/mastodon/features/explore/links.jsx
+++ b/app/javascript/mastodon/features/explore/links.jsx
@@ -7,7 +7,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import { fetchTrendingLinks } from 'mastodon/actions/trends';
-import DismissableBanner from 'mastodon/components/dismissable_banner';
+import { DismissableBanner } from 'mastodon/components/dismissable_banner';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import Story from './components/story';
diff --git a/app/javascript/mastodon/features/explore/statuses.jsx b/app/javascript/mastodon/features/explore/statuses.jsx
index eb2fe777a..3271929db 100644
--- a/app/javascript/mastodon/features/explore/statuses.jsx
+++ b/app/javascript/mastodon/features/explore/statuses.jsx
@@ -9,7 +9,7 @@ import { connect } from 'react-redux';
import { debounce } from 'lodash';
import { fetchTrendingStatuses, expandTrendingStatuses } from 'mastodon/actions/trends';
-import DismissableBanner from 'mastodon/components/dismissable_banner';
+import { DismissableBanner } from 'mastodon/components/dismissable_banner';
import StatusList from 'mastodon/components/status_list';
import { getStatusList } from 'mastodon/selectors';
diff --git a/app/javascript/mastodon/features/explore/tags.jsx b/app/javascript/mastodon/features/explore/tags.jsx
index f558b48a6..1a4d25969 100644
--- a/app/javascript/mastodon/features/explore/tags.jsx
+++ b/app/javascript/mastodon/features/explore/tags.jsx
@@ -7,7 +7,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import { fetchTrendingHashtags } from 'mastodon/actions/trends';
-import DismissableBanner from 'mastodon/components/dismissable_banner';
+import { DismissableBanner } from 'mastodon/components/dismissable_banner';
import { ImmutableHashtag as Hashtag } from 'mastodon/components/hashtag';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
diff --git a/app/javascript/mastodon/features/firehose/index.jsx b/app/javascript/mastodon/features/firehose/index.jsx
index 9ba4fd5b2..e5b47d3fe 100644
--- a/app/javascript/mastodon/features/firehose/index.jsx
+++ b/app/javascript/mastodon/features/firehose/index.jsx
@@ -10,7 +10,7 @@ import { addColumn } from 'mastodon/actions/columns';
import { changeSetting } from 'mastodon/actions/settings';
import { connectPublicStream, connectCommunityStream } from 'mastodon/actions/streaming';
import { expandPublicTimeline, expandCommunityTimeline } from 'mastodon/actions/timelines';
-import DismissableBanner from 'mastodon/components/dismissable_banner';
+import { DismissableBanner } from 'mastodon/components/dismissable_banner';
import initialState, { domain } from 'mastodon/initial_state';
import { useAppDispatch, useAppSelector } from 'mastodon/store';
diff --git a/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx b/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx
index a6993c641..2af85b6d5 100644
--- a/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx
+++ b/app/javascript/mastodon/features/home_timeline/components/explore_prompt.jsx
@@ -5,7 +5,7 @@ import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import background from 'mastodon/../images/friends-cropped.png';
-import DismissableBanner from 'mastodon/components/dismissable_banner';
+import { DismissableBanner } from 'mastodon/components/dismissable_banner';
export const ExplorePrompt = () => (
diff --git a/app/javascript/mastodon/features/public_timeline/index.jsx b/app/javascript/mastodon/features/public_timeline/index.jsx
index 352baa833..3bfb25ba7 100644
--- a/app/javascript/mastodon/features/public_timeline/index.jsx
+++ b/app/javascript/mastodon/features/public_timeline/index.jsx
@@ -7,7 +7,7 @@ import { Helmet } from 'react-helmet';
import { connect } from 'react-redux';
-import DismissableBanner from 'mastodon/components/dismissable_banner';
+import { DismissableBanner } from 'mastodon/components/dismissable_banner';
import { domain } from 'mastodon/initial_state';
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';