diff --git a/ui/app/contexts/metametrics.js b/ui/app/contexts/metametrics.js
new file mode 100644
index 000000000..0e811585d
--- /dev/null
+++ b/ui/app/contexts/metametrics.js
@@ -0,0 +1,131 @@
+import React, { Component, createContext, useEffect, useCallback, useState } from 'react'
+import { useSelector } from 'react-redux'
+import PropTypes from 'prop-types'
+import { useHistory } from 'react-router-dom'
+import { captureException } from '@sentry/browser'
+
+import {
+ getCurrentNetworkId,
+ getSelectedAsset,
+ getAccountType,
+ getNumberOfAccounts,
+ getNumberOfTokens,
+} from '../selectors/selectors'
+import {
+ txDataSelector,
+} from '../selectors/confirm-transaction'
+import { getEnvironmentType } from '../../../app/scripts/lib/util'
+import {
+ sendMetaMetricsEvent,
+ sendCountIsTrackable,
+} from '../helpers/utils/metametrics.util'
+
+
+export const MetaMetricsContext = createContext(() => {
+ captureException(
+ Error(`MetaMetrics context function was called from a react node that is not a descendant of a MetaMetrics context provider`)
+ )
+})
+
+export function MetaMetricsProvider ({ children }) {
+ const txData = useSelector(txDataSelector) || {}
+ const network = useSelector(getCurrentNetworkId)
+ const environmentType = getEnvironmentType()
+ const activeCurrency = useSelector(getSelectedAsset)
+ const accountType = useSelector(getAccountType)
+ const confirmTransactionOrigin = txData.origin
+ const metaMetricsId = useSelector((state) => state.metamask.metaMetricsId)
+ const participateInMetaMetrics = useSelector((state) => state.metamask.participateInMetaMetrics)
+ const metaMetricsSendCount = useSelector((state) => state.metamask.metaMetricsSendCount)
+ const numberOfTokens = useSelector(getNumberOfTokens)
+ const numberOfAccounts = useSelector(getNumberOfAccounts)
+ const history = useHistory()
+ const [state, setState] = useState(() => ({
+ currentPath: window.location.href,
+ previousPath: '',
+ }))
+
+ const { previousPath, currentPath } = state
+
+ useEffect(() => {
+ const unlisten = history.listen(() => setState((prevState) => ({
+ currentPath: window.location.href,
+ previousPath: prevState.currentPath,
+ })))
+ // remove this listener if the component is no longer mounted
+ return unlisten
+ }, [history])
+
+ const metricsEvent = useCallback((config = {}, overrides = {}) => {
+ const { eventOpts = {} } = config
+ const { name = '' } = eventOpts
+ const { pathname: overRidePathName = '' } = overrides
+ const isSendFlow = Boolean(name.match(/^send|^confirm/) || overRidePathName.match(/send|confirm/))
+
+ if (participateInMetaMetrics || config.isOptIn) {
+ return sendMetaMetricsEvent({
+ network,
+ environmentType,
+ activeCurrency,
+ accountType,
+ confirmTransactionOrigin,
+ metaMetricsId,
+ numberOfTokens,
+ numberOfAccounts,
+ version: global.platform.getVersion(),
+ ...config,
+ previousPath,
+ currentPath,
+ excludeMetaMetricsId: isSendFlow && !sendCountIsTrackable(metaMetricsSendCount + 1),
+ ...overrides,
+ })
+ }
+ }, [
+ network,
+ environmentType,
+ activeCurrency,
+ accountType,
+ confirmTransactionOrigin,
+ participateInMetaMetrics,
+ previousPath,
+ metaMetricsId,
+ numberOfTokens,
+ numberOfAccounts,
+ currentPath,
+ metaMetricsSendCount,
+ ])
+
+ return (
+
+ {children}
+
+ )
+}
+
+MetaMetricsProvider.propTypes = { children: PropTypes.node }
+
+export class LegacyMetaMetricsProvider extends Component {
+ static propTypes = {
+ children: PropTypes.node,
+ }
+
+ static defaultProps = {
+ children: undefined,
+ }
+
+ static contextType = MetaMetricsContext
+
+ static childContextTypes = {
+ metricsEvent: PropTypes.func,
+ }
+
+ getChildContext () {
+ return {
+ metricsEvent: this.context,
+ }
+ }
+
+ render () {
+ return this.props.children
+ }
+}
diff --git a/ui/app/helpers/higher-order-components/metametrics/metametrics.provider.js b/ui/app/helpers/higher-order-components/metametrics/metametrics.provider.js
deleted file mode 100644
index e67ab9a21..000000000
--- a/ui/app/helpers/higher-order-components/metametrics/metametrics.provider.js
+++ /dev/null
@@ -1,130 +0,0 @@
-import { Component } from 'react'
-import { connect } from 'react-redux'
-import PropTypes from 'prop-types'
-import { withRouter } from 'react-router-dom'
-import { compose } from 'redux'
-import {
- getCurrentNetworkId,
- getSelectedAsset,
- getAccountType,
- getNumberOfAccounts,
- getNumberOfTokens,
- txDataSelector,
-} from '../../../selectors'
-
-import { getEnvironmentType } from '../../../../../app/scripts/lib/util'
-import {
- sendMetaMetricsEvent,
- sendCountIsTrackable,
-} from '../../utils/metametrics.util'
-
-class MetaMetricsProvider extends Component {
- static propTypes = {
- accountType: PropTypes.string.isRequired,
- activeCurrency: PropTypes.string.isRequired,
- children: PropTypes.object.isRequired,
- confirmTransactionOrigin: PropTypes.string,
- environmentType: PropTypes.string.isRequired,
- history: PropTypes.object.isRequired,
- metaMetricsId: PropTypes.string,
- metaMetricsSendCount: PropTypes.number.isRequired,
- network: PropTypes.string.isRequired,
- numberOfTokens: PropTypes.number,
- numberOfAccounts: PropTypes.number,
- participateInMetaMetrics: PropTypes.bool,
- version: PropTypes.string,
- }
-
- static childContextTypes = {
- metricsEvent: PropTypes.func,
- }
-
- constructor (props) {
- super(props)
-
- props.history.listen(() => {
- this.setState((prevState) => ({
- previousPath: prevState.currentPath,
- currentPath: window.location.href,
- }))
- })
- }
-
- state = {
- previousPath: '',
- currentPath: window.location.href,
- }
-
- getChildContext () {
- const {
- network,
- environmentType,
- activeCurrency,
- accountType,
- confirmTransactionOrigin,
- metaMetricsId,
- participateInMetaMetrics,
- metaMetricsSendCount,
- numberOfTokens,
- numberOfAccounts,
- version,
- } = this.props
- const { previousPath, currentPath } = this.state
-
- return {
- metricsEvent: (config = {}, overrides = {}) => {
- const { eventOpts = {} } = config
- const { name = '' } = eventOpts
- const { pathname: overRidePathName = '' } = overrides
- const isSendFlow = Boolean(name.match(/^send|^confirm/) || overRidePathName.match(/send|confirm/))
-
- if (participateInMetaMetrics || config.isOptIn) {
- return sendMetaMetricsEvent({
- network,
- environmentType,
- activeCurrency,
- accountType,
- confirmTransactionOrigin,
- metaMetricsId,
- numberOfTokens,
- numberOfAccounts,
- version,
- ...config,
- previousPath,
- currentPath,
- excludeMetaMetricsId: isSendFlow && !sendCountIsTrackable(metaMetricsSendCount + 1),
- ...overrides,
- })
- }
- },
- }
- }
-
- render () {
- return this.props.children
- }
-}
-
-const mapStateToProps = (state) => {
- const txData = txDataSelector(state) || {}
-
- return {
- network: getCurrentNetworkId(state),
- environmentType: getEnvironmentType(),
- activeCurrency: getSelectedAsset(state),
- accountType: getAccountType(state),
- confirmTransactionOrigin: txData.origin,
- metaMetricsId: state.metamask.metaMetricsId,
- participateInMetaMetrics: state.metamask.participateInMetaMetrics,
- metaMetricsSendCount: state.metamask.metaMetricsSendCount,
- numberOfTokens: getNumberOfTokens(state),
- numberOfAccounts: getNumberOfAccounts(state),
- version: global.platform.getVersion(),
- }
-}
-
-export default compose(
- withRouter,
- connect(mapStateToProps)
-)(MetaMetricsProvider)
-
diff --git a/ui/app/hooks/useMetricEvent.js b/ui/app/hooks/useMetricEvent.js
new file mode 100644
index 000000000..33ca751ec
--- /dev/null
+++ b/ui/app/hooks/useMetricEvent.js
@@ -0,0 +1,9 @@
+import { useContext, useCallback } from 'react'
+import { MetaMetricsContext } from '../contexts/metametrics'
+
+
+export function useMetricEvent (config = {}, overrides = {}) {
+ const metricsEvent = useContext(MetaMetricsContext)
+ const trackEvent = useCallback(() => metricsEvent(config, overrides), [config, overrides])
+ return trackEvent
+}
diff --git a/ui/app/pages/index.js b/ui/app/pages/index.js
index 3d8ccf165..5ec61b4d2 100644
--- a/ui/app/pages/index.js
+++ b/ui/app/pages/index.js
@@ -6,7 +6,7 @@ import * as Sentry from '@sentry/browser'
import ErrorPage from './error'
import Routes from './routes'
import { I18nProvider, LegacyI18nProvider } from '../contexts/i18n'
-import MetaMetricsProvider from '../helpers/higher-order-components/metametrics/metametrics.provider'
+import { MetaMetricsProvider, LegacyMetaMetricsProvider } from '../contexts/metametrics'
class Index extends PureComponent {
state = {}
@@ -42,11 +42,13 @@ class Index extends PureComponent {
-
-
-
-
-
+
+
+
+
+
+
+