From 26fa36083e54037194b9fa5312ceb17d65bb616a Mon Sep 17 00:00:00 2001 From: zhangchen Date: Thu, 2 Jul 2020 10:46:47 +0800 Subject: [PATCH] fix: ResponsiveObserve unsubscribe (#25309) (#25319) * fix: ResponsiveObserve unsubscribe (#25309) * fix: ResponsiveObserve unsubscribe (#25309) * fix: ResponsiveObserve unsubscribe * test: add responsiveObserve.test.js --- .../_util/__tests__/responsiveObserve.test.js | 14 ++++++ components/_util/responsiveObserve.ts | 47 ++++++++----------- components/grid/row.tsx | 2 +- 3 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 components/_util/__tests__/responsiveObserve.test.js diff --git a/components/_util/__tests__/responsiveObserve.test.js b/components/_util/__tests__/responsiveObserve.test.js new file mode 100644 index 0000000000..995095d08e --- /dev/null +++ b/components/_util/__tests__/responsiveObserve.test.js @@ -0,0 +1,14 @@ +import ResponsiveObserve, { responsiveMap } from '../responsiveObserve'; + +describe('Test ResponsiveObserve', () => { + it('test ResponsiveObserve subscribe and unsubscribe', () => { + const { xs } = responsiveMap; + const subscribeFunc = jest.fn(); + const token = ResponsiveObserve.subscribe(subscribeFunc); + expect(ResponsiveObserve.matchHandlers[xs].mql.matches).toBeTruthy(); + expect(subscribeFunc).toBeCalledTimes(1); + + ResponsiveObserve.unsubscribe(token); + expect(ResponsiveObserve.matchHandlers[xs].mql.removeListener).toBeCalled(); + }); +}); diff --git a/components/_util/responsiveObserve.ts b/components/_util/responsiveObserve.ts index 191cbaa970..b4b7446648 100644 --- a/components/_util/responsiveObserve.ts +++ b/components/_util/responsiveObserve.ts @@ -14,49 +14,40 @@ export const responsiveMap: BreakpointMap = { }; type SubscribeFunc = (screens: ScreenMap) => void; - -let subscribers: Array<{ - token: string; - func: SubscribeFunc; -}> = []; +const subscribers = new Map(); let subUid = -1; let screens = {}; const responsiveObserve = { - matchHandlers: {}, + matchHandlers: {} as { + [prop: string]: { + mql: MediaQueryList; + listener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | null; + }; + }, dispatch(pointMap: ScreenMap) { screens = pointMap; - subscribers.forEach(item => { - item.func(screens); - }); - return subscribers.length >= 1; + subscribers.forEach(func => func(screens)); + return subscribers.size >= 1; }, - subscribe(func: SubscribeFunc) { - if (subscribers.length === 0) { - this.register(); - } - const token = (++subUid).toString(); - subscribers.push({ - token, - func, - }); + subscribe(func: SubscribeFunc): number { + if (!subscribers.size) this.register(); + subUid += 1; + subscribers.set(subUid, func); func(screens); - return token; + return subUid; }, - unsubscribe(token: string) { - subscribers = subscribers.filter(item => item.token !== token); - if (subscribers.length === 0) { - this.unregister(); - } + unsubscribe(token: number) { + subscribers.delete(token); + if (!subscribers.size) this.unregister(); }, unregister() { Object.keys(responsiveMap).forEach((screen: Breakpoint) => { const matchMediaQuery = responsiveMap[screen]!; const handler = this.matchHandlers[matchMediaQuery]; - if (handler && handler.mql && handler.listener) { - handler.mql.removeListener(handler.listener); - } + handler?.mql.removeListener(handler?.listener); }); + subscribers.clear(); }, register() { Object.keys(responsiveMap).forEach((screen: Breakpoint) => { diff --git a/components/grid/row.tsx b/components/grid/row.tsx index 25a789cb8c..cb5e6d7591 100644 --- a/components/grid/row.tsx +++ b/components/grid/row.tsx @@ -40,7 +40,7 @@ export default class Row extends React.Component { }, }; - token: string; + token: number; componentDidMount() { this.token = ResponsiveObserve.subscribe(screens => {