diff --git a/ui/src/alerting/components/notifications/EditRuleOverlay.tsx b/ui/src/alerting/components/notifications/EditRuleOverlay.tsx index ca93f39493..11ea4d3535 100644 --- a/ui/src/alerting/components/notifications/EditRuleOverlay.tsx +++ b/ui/src/alerting/components/notifications/EditRuleOverlay.tsx @@ -7,11 +7,8 @@ import {connect} from 'react-redux' import {Overlay} from '@influxdata/clockface' import RuleOverlayContents from 'src/alerting/components/notifications/RuleOverlayContents' -// Reducers -import {memoizedReducer, ActionPayload} from './RuleOverlay.reducer' - -// Constants -import {RuleModeContext, EditRuleDispatch, RuleMode} from 'src/shared/hooks' +// Utils +import {RuleOverlayProvider} from './RuleOverlay.reducer' // Types import {NotificationRuleDraft, AppState} from 'src/types' @@ -31,28 +28,20 @@ const EditRuleOverlay: FC = ({params, router, stateRule}) => { router.push(`/orgs/${params.orgID}/alerting`) } - const mode = RuleMode.Edit - const [rule, dispatch] = memoizedReducer(mode, stateRule) - const ruleDispatch = (action: ActionPayload): void => { - dispatch({...action, mode}) - } - return ( - - - - - - - - - - - - + + + + + + + + + + ) } diff --git a/ui/src/alerting/components/notifications/NewRuleOverlay.tsx b/ui/src/alerting/components/notifications/NewRuleOverlay.tsx index 88abfda12c..b19bc40153 100644 --- a/ui/src/alerting/components/notifications/NewRuleOverlay.tsx +++ b/ui/src/alerting/components/notifications/NewRuleOverlay.tsx @@ -1,20 +1,17 @@ // Libraries -import React, {FC, useReducer, useCallback} from 'react' +import React, {FC} from 'react' import {withRouter, WithRouterProps} from 'react-router' // Components import RuleOverlayContents from 'src/alerting/components/notifications/RuleOverlayContents' import {Overlay} from '@influxdata/clockface' -// Reducers -import {reducer, ActionPayload} from './RuleOverlay.reducer' +// Utils +import {RuleOverlayProvider} from './RuleOverlay.reducer' // Constants import {newRule} from 'src/alerting/constants' -// Context -import {RuleMode, NewRuleDispatch, RuleModeContext} from 'src/shared/hooks' - type Props = WithRouterProps const NewRuleOverlay: FC = ({params, router}) => { @@ -22,30 +19,20 @@ const NewRuleOverlay: FC = ({params, router}) => { router.push(`/orgs/${params.orgID}/alerting`) } - const mode = RuleMode.New - const memoizedReducer = useCallback(reducer(mode), []) - const [rule, dispatch] = useReducer(memoizedReducer, newRule) - - const ruleDispatch = (action: ActionPayload) => { - dispatch({...action, mode}) - } - return ( - - - - - - - - - - - - + + + + + + + + + + ) } diff --git a/ui/src/alerting/components/notifications/RuleConditions.tsx b/ui/src/alerting/components/notifications/RuleConditions.tsx index eead341099..3ebbee71cc 100644 --- a/ui/src/alerting/components/notifications/RuleConditions.tsx +++ b/ui/src/alerting/components/notifications/RuleConditions.tsx @@ -15,15 +15,15 @@ import StatusRuleComponent from 'src/alerting/components/notifications/StatusRul import TagRuleComponent from 'src/alerting/components/notifications/TagRule' import DashedButton from 'src/shared/components/dashed_button/DashedButton' +// Utils +import {useRuleDispatch} from './RuleOverlay.reducer' + // Constants import {newTagRule} from 'src/alerting/constants' // Types import {RuleState} from './RuleOverlay.reducer' -// Hooks -import {useRuleDispatch} from 'src/shared/hooks' - interface Props { rule: RuleState } diff --git a/ui/src/alerting/components/notifications/RuleMessage.tsx b/ui/src/alerting/components/notifications/RuleMessage.tsx index 645ea7ace8..54001c02a5 100644 --- a/ui/src/alerting/components/notifications/RuleMessage.tsx +++ b/ui/src/alerting/components/notifications/RuleMessage.tsx @@ -6,14 +6,12 @@ import {Form, Panel, Grid, Columns} from '@influxdata/clockface' import RuleEndpointDropdown from 'src/alerting/components/notifications/RuleEndpointDropdown' import RuleMessageContents from 'src/alerting/components/notifications/RuleMessageContents' -// Types -import {NotificationEndpoint, NotificationRuleDraft} from 'src/types' - // Utils import {getEndpointBase} from 'src/alerting/components/notifications/utils' +import {useRuleDispatch} from './RuleOverlay.reducer' -// Hooks -import {useRuleDispatch} from 'src/shared/hooks' +// Types +import {NotificationEndpoint, NotificationRuleDraft} from 'src/types' interface Props { endpoints: NotificationEndpoint[] diff --git a/ui/src/alerting/components/notifications/RuleMessageContents.tsx b/ui/src/alerting/components/notifications/RuleMessageContents.tsx index 71c7ed59a9..4ef260f1a7 100644 --- a/ui/src/alerting/components/notifications/RuleMessageContents.tsx +++ b/ui/src/alerting/components/notifications/RuleMessageContents.tsx @@ -6,12 +6,12 @@ import SlackMessage from './SlackMessage' import SMTPMessage from './SMTPMessage' import PagerDutyMessage from './PagerDutyMessage' +// Utils +import {useRuleDispatch} from './RuleOverlay.reducer' + // Types import {NotificationRuleDraft} from 'src/types' -// Hooks -import {useRuleDispatch} from 'src/shared/hooks' - interface Props { rule: NotificationRuleDraft } diff --git a/ui/src/alerting/components/notifications/RuleOverlay.reducer.ts b/ui/src/alerting/components/notifications/RuleOverlay.reducer.tsx similarity index 73% rename from ui/src/alerting/components/notifications/RuleOverlay.reducer.ts rename to ui/src/alerting/components/notifications/RuleOverlay.reducer.tsx index 14e3ae3b14..afe96378fd 100644 --- a/ui/src/alerting/components/notifications/RuleOverlay.reducer.ts +++ b/ui/src/alerting/components/notifications/RuleOverlay.reducer.tsx @@ -1,5 +1,12 @@ // Libraries -import {useCallback, useReducer} from 'react' +import React, { + createContext, + useContext, + useReducer, + useRef, + Dispatch, + FC, +} from 'react' import {v4} from 'uuid' import {omit} from 'lodash' @@ -11,13 +18,11 @@ import { CheckStatusLevel, } from 'src/types' -// Hooks -import {RuleMode} from 'src/shared/hooks' - export type LevelType = 'currentLevel' | 'previousLevel' + export type RuleState = NotificationRuleDraft -export type ActionMode = {mode: RuleMode} -export type ActionPayload = + +export type Action = | {type: 'UPDATE_RULE'; rule: NotificationRuleDraft} | { type: 'UPDATE_STATUS_LEVEL' @@ -37,16 +42,7 @@ export type ActionPayload = operator: TagRuleDraft['value']['operator'] } -export type Action = ActionPayload & ActionMode - -export const reducer = (mode: RuleMode) => ( - state: RuleState, - action: Action -) => { - if (mode !== action.mode) { - return state - } - +const reducer = (state: RuleState, action: Action) => { switch (action.type) { case 'UPDATE_RULE': { const {rule} = action @@ -167,13 +163,47 @@ export const reducer = (mode: RuleMode) => ( default: const neverAction: never = action + throw new Error( - `Unhandled action: "${neverAction}" in RuleOverlay.reducer.ts` + `Unhandled action "${ + (neverAction as any).type + }" in RuleOverlay.reducer.ts` ) } } -export const memoizedReducer = (mode: RuleMode, state) => { - const memo = useCallback(reducer(mode), [mode]) - return useReducer(memo, state) +const RuleStateContext = createContext(null) +const RuleDispatchContext = createContext>(null) + +export const RuleOverlayProvider: FC<{initialState: RuleState}> = ({ + initialState, + children, +}) => { + const prevInitialStateRef = useRef(initialState) + + const [state, dispatch] = useReducer((state: RuleState, action: Action) => { + if (prevInitialStateRef.current !== initialState) { + prevInitialStateRef.current = initialState + + return initialState + } + + return reducer(state, action) + }, initialState) + + return ( + + + {children} + + + ) +} + +export const useRuleState = (): RuleState => { + return useContext(RuleStateContext) +} + +export const useRuleDispatch = (): Dispatch => { + return useContext(RuleDispatchContext) } diff --git a/ui/src/alerting/components/notifications/RuleOverlayContents.tsx b/ui/src/alerting/components/notifications/RuleOverlayContents.tsx index 772dc3f83d..6d9a1ba04f 100644 --- a/ui/src/alerting/components/notifications/RuleOverlayContents.tsx +++ b/ui/src/alerting/components/notifications/RuleOverlayContents.tsx @@ -14,23 +14,22 @@ import RuleSchedule from 'src/alerting/components/notifications/RuleSchedule' import RuleConditions from 'src/alerting/components/notifications/RuleConditions' import RuleMessage from 'src/alerting/components/notifications/RuleMessage' -// Types -import {NotificationRuleDraft} from 'src/types' - // Constants import {endpoints} from 'src/alerting/constants' -// Hooks -import {useRuleDispatch} from 'src/shared/hooks' +// Utils +import {useRuleState, useRuleDispatch} from './RuleOverlay.reducer' -interface Props { - rule: NotificationRuleDraft -} +// Types +import {NotificationRuleDraft} from 'src/types' -const RuleOverlayContents: FC = ({rule}) => { +const RuleOverlayContents: FC = () => { + const rule = useRuleState() const dispatch = useRuleDispatch() + const handleChange = e => { const {name, value} = e.target + dispatch({ type: 'UPDATE_RULE', rule: {...rule, [name]: value} as NotificationRuleDraft, diff --git a/ui/src/alerting/components/notifications/RuleSchedule.tsx b/ui/src/alerting/components/notifications/RuleSchedule.tsx index ebfe82c00c..080508658a 100644 --- a/ui/src/alerting/components/notifications/RuleSchedule.tsx +++ b/ui/src/alerting/components/notifications/RuleSchedule.tsx @@ -12,8 +12,8 @@ import { ButtonShape, } from '@influxdata/clockface' -// Hooks -import {useRuleDispatch} from 'src/shared/hooks' +// Utils +import {useRuleDispatch} from './RuleOverlay.reducer' // Types import {RuleState} from './RuleOverlay.reducer' diff --git a/ui/src/alerting/components/notifications/StatusChangeDropdown.tsx b/ui/src/alerting/components/notifications/StatusChangeDropdown.tsx index 4f93b60ca4..0af2d11231 100644 --- a/ui/src/alerting/components/notifications/StatusChangeDropdown.tsx +++ b/ui/src/alerting/components/notifications/StatusChangeDropdown.tsx @@ -8,15 +8,13 @@ import {StatusRuleDraft} from 'src/types' import {Dropdown} from '@influxdata/clockface' // Utils +import {useRuleDispatch} from './RuleOverlay.reducer' import { CHANGES, changeStatusRule, activeChange, } from 'src/alerting/components/notifications/utils' -// Hooks -import {useRuleDispatch} from 'src/shared/hooks' - interface Props { status: StatusRuleDraft } diff --git a/ui/src/alerting/components/notifications/StatusLevels.tsx b/ui/src/alerting/components/notifications/StatusLevels.tsx index c75d184466..81bae3988f 100644 --- a/ui/src/alerting/components/notifications/StatusLevels.tsx +++ b/ui/src/alerting/components/notifications/StatusLevels.tsx @@ -12,12 +12,12 @@ import LevelsDropdown from 'src/alerting/components/notifications/LevelsDropdown import StatusChangeDropdown from 'src/alerting/components/notifications/StatusChangeDropdown' import {LevelType} from 'src/alerting/components/notifications/RuleOverlay.reducer' +// Utils +import {useRuleDispatch} from './RuleOverlay.reducer' + // Types import {StatusRuleDraft, CheckStatusLevel} from 'src/types' -// Hooks -import {useRuleDispatch} from 'src/shared/hooks' - interface Props { status: StatusRuleDraft } diff --git a/ui/src/alerting/components/notifications/TagRule.tsx b/ui/src/alerting/components/notifications/TagRule.tsx index 6533ae316e..51304a9a2a 100644 --- a/ui/src/alerting/components/notifications/TagRule.tsx +++ b/ui/src/alerting/components/notifications/TagRule.tsx @@ -12,16 +12,17 @@ import { FlexDirection, ComponentColor, } from '@influxdata/clockface' + import TagRuleOperatorDropdown, { Operator, } from 'src/alerting/components/notifications/TagRuleOperatorDropdown' +// Utils +import {useRuleDispatch} from './RuleOverlay.reducer' + // Types import {TagRuleDraft} from 'src/types' -// Hooks -import {useRuleDispatch} from 'src/shared/hooks' - interface Props { tagRule: TagRuleDraft } diff --git a/ui/src/shared/hooks/index.ts b/ui/src/shared/hooks/index.ts deleted file mode 100644 index f4bca2fc71..0000000000 --- a/ui/src/shared/hooks/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -import React, {useContext} from 'react' - -import {ActionPayload} from 'src/alerting/components/notifications/RuleOverlay.reducer' - -export enum RuleMode { - New = 'NewRuleDispatch', - Edit = 'EditRuleDispatch', -} - -export const RuleModeContext = React.createContext(null) -export const NewRuleDispatch = React.createContext< - (action: ActionPayload) => void ->(null) -export const EditRuleDispatch = React.createContext< - (action: ActionPayload) => void ->(null) - -interface Contexts { - NewRuleDispatch: typeof NewRuleDispatch - EditRuleDispatch: typeof EditRuleDispatch -} - -export const contexts: Contexts = { - NewRuleDispatch, - EditRuleDispatch, -} - -export const useRuleDispatch = () => { - const mode = useContext(RuleModeContext) - - return useContext(contexts[mode]) -}