fix: ResponsiveObserve unsubscribe (#25309) (#25319)

* fix: ResponsiveObserve unsubscribe (#25309)

* fix: ResponsiveObserve unsubscribe (#25309)

* fix: ResponsiveObserve unsubscribe

* test: add responsiveObserve.test.js
This commit is contained in:
zhangchen 2020-07-02 10:46:47 +08:00 committed by GitHub
parent e3982e94f8
commit 26fa36083e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 29 deletions

View File

@ -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();
});
});

View File

@ -14,49 +14,40 @@ export const responsiveMap: BreakpointMap = {
}; };
type SubscribeFunc = (screens: ScreenMap) => void; type SubscribeFunc = (screens: ScreenMap) => void;
const subscribers = new Map<Number, SubscribeFunc>();
let subscribers: Array<{
token: string;
func: SubscribeFunc;
}> = [];
let subUid = -1; let subUid = -1;
let screens = {}; let screens = {};
const responsiveObserve = { const responsiveObserve = {
matchHandlers: {}, matchHandlers: {} as {
[prop: string]: {
mql: MediaQueryList;
listener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | null;
};
},
dispatch(pointMap: ScreenMap) { dispatch(pointMap: ScreenMap) {
screens = pointMap; screens = pointMap;
subscribers.forEach(item => { subscribers.forEach(func => func(screens));
item.func(screens); return subscribers.size >= 1;
});
return subscribers.length >= 1;
}, },
subscribe(func: SubscribeFunc) { subscribe(func: SubscribeFunc): number {
if (subscribers.length === 0) { if (!subscribers.size) this.register();
this.register(); subUid += 1;
} subscribers.set(subUid, func);
const token = (++subUid).toString();
subscribers.push({
token,
func,
});
func(screens); func(screens);
return token; return subUid;
}, },
unsubscribe(token: string) { unsubscribe(token: number) {
subscribers = subscribers.filter(item => item.token !== token); subscribers.delete(token);
if (subscribers.length === 0) { if (!subscribers.size) this.unregister();
this.unregister();
}
}, },
unregister() { unregister() {
Object.keys(responsiveMap).forEach((screen: Breakpoint) => { Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
const matchMediaQuery = responsiveMap[screen]!; const matchMediaQuery = responsiveMap[screen]!;
const handler = this.matchHandlers[matchMediaQuery]; const handler = this.matchHandlers[matchMediaQuery];
if (handler && handler.mql && handler.listener) { handler?.mql.removeListener(handler?.listener);
handler.mql.removeListener(handler.listener);
}
}); });
subscribers.clear();
}, },
register() { register() {
Object.keys(responsiveMap).forEach((screen: Breakpoint) => { Object.keys(responsiveMap).forEach((screen: Breakpoint) => {

View File

@ -40,7 +40,7 @@ export default class Row extends React.Component<RowProps, RowState> {
}, },
}; };
token: string; token: number;
componentDidMount() { componentDidMount() {
this.token = ResponsiveObserve.subscribe(screens => { this.token = ResponsiveObserve.subscribe(screens => {