Skip to content
This repository has been archived by the owner on Mar 7, 2024. It is now read-only.

Commit

Permalink
fix: 生命周期 hooks 不能在组件中使用的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
yesmeck committed Aug 22, 2019
1 parent e34c366 commit 4fa5695
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 77 deletions.
170 changes: 104 additions & 66 deletions packages/remax/src/__tests__/alipay/page.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,75 +26,113 @@ describe('page', () => {
expect(page.config.wrapper).not.toBeNull();
});

it('lifecycle hooks', () => {
const log: string[] = [];
const Foo: React.FC<PageProps> = () => {
useShow(() => {
log.push('useShow');
});

useHide(() => {
log.push('useHide');
});

usePullDownRefresh(() => {
log.push('usePullDownRefresh');
});

useReachBottom(() => {
log.push('useReachBottom');
});

usePageScroll(() => {
log.push('usePageScroll');
});
describe('hooks', () => {
it('works', () => {
const log: string[] = [];
const Foo: React.FC<PageProps> = () => {
useShow(() => {
log.push('useShow');
});

useHide(() => {
log.push('useHide');
});

usePullDownRefresh(() => {
log.push('usePullDownRefresh');
});

useReachBottom(() => {
log.push('useReachBottom');
});

usePageScroll(() => {
log.push('usePageScroll');
});

useShareAppMessage(() => {
log.push('useShareAppMessage');
});

useTitleClick(() => {
log.push('useTitleClick');
});

useOptionMenuClick(() => {
log.push('useOptionMenuClick');
});

usePopMenuClick(() => {
log.push('usePopMenuClick');
});

usePullIntercept(() => {
log.push('usePullIntercept');
});

useShareAppMessage(() => {
log.push('useShareAppMessage');
});

useTitleClick(() => {
log.push('useTitleClick');
});

useOptionMenuClick(() => {
log.push('useOptionMenuClick');
});

usePopMenuClick(() => {
log.push('usePopMenuClick');
});
return <View>foo</View>;
};
const page = Page(createPageConfig(Foo));
page.load();
page.pullDownRefresh();
page.pullIntercept();
page.reachBottom();
page.pageScroll();
page.shareAppMessage();
page.titleClick();
page.optionMenuClick();
page.popMenuClick();
page.hide();

expect(log).toEqual([
'useShow',
'usePullDownRefresh',
'usePullIntercept',
'useReachBottom',
'usePageScroll',
'useShareAppMessage',
'useTitleClick',
'useOptionMenuClick',
'usePopMenuClick',
'useHide',
]);
});

it('works in component', () => {
const log: string[] = [];
const Foo = () => {
useShow(() => {
log.push('onShow');
});
return <View>foo</View>;
};
const Bar = () => <Foo />;
const page = Page(createPageConfig(Bar));
page.load();
expect(log).toEqual(['onShow']);
});

it('register once', () => {
const log: string[] = [];
const foo = React.createRef<any>();
const Foo = React.forwardRef((props, ref) => {
const [_, forceUpdate] = React.useState(0);

useShow(() => {
log.push('onShow');
});

React.useImperativeHandle(ref, () => ({
forceUpdate,
}));

usePullIntercept(() => {
log.push('usePullIntercept');
return <View>foo</View>;
});

return <View>foo</View>;
};
const page = Page(createPageConfig(Foo));
page.load();
page.pullDownRefresh();
page.pullIntercept();
page.reachBottom();
page.pageScroll();
page.shareAppMessage();
page.titleClick();
page.optionMenuClick();
page.popMenuClick();
page.hide();

expect(log).toEqual([
'useShow',
'usePullDownRefresh',
'usePullIntercept',
'useReachBottom',
'usePageScroll',
'useShareAppMessage',
'useTitleClick',
'useOptionMenuClick',
'usePopMenuClick',
'useHide',
]);
const page = Page(createPageConfig(() => <Foo ref={foo} />));
page.load();
foo.current.forceUpdate();
expect(log).toEqual(['onShow']);
});
});

it('lifecycle methods', () => {
Expand Down
7 changes: 7 additions & 0 deletions packages/remax/src/createPageConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ export default function createPageConfig(Page: React.ComponentType<any>) {
this.lifecycleCallback[lifecycle] || [];

this.lifecycleCallback[lifecycle].push(callback);

return () => {
this.lifecycleCallback[lifecycle].splice(
this.lifecycleCallback[lifecycle].indexOf(callback),
1
);
};
},

callLifecycle(lifecycle: Lifecycle) {
Expand Down
41 changes: 31 additions & 10 deletions packages/remax/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,62 @@
import { useLayoutEffect } from 'react';
import { registerLifecycle, Lifecycle, Callback } from './lifecycle';

export function useShow(callback: Callback) {
return registerLifecycle(Lifecycle.show, callback);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.show, callback);
}, []);
}

export function useHide(callback: Callback) {
return registerLifecycle(Lifecycle.hide, callback);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.hide, callback);
}, []);
}

export function usePullDownRefresh(callback: Callback) {
return registerLifecycle(Lifecycle.pullDownRefresh, callback);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.pullDownRefresh, callback);
}, []);
}

export function useReachBottom(callback: Callback) {
return registerLifecycle(Lifecycle.reachBottom, callback);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.reachBottom, callback);
}, []);
}

export function usePageScroll(callback: Callback) {
return registerLifecycle(Lifecycle.pageScroll, callback);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.pageScroll, callback);
}, []);
}

export function useShareAppMessage(callback: Callback) {
return registerLifecycle(Lifecycle.shareAppMessage, callback);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.shareAppMessage, callback);
}, []);
}

export function useTitleClick(callback: Callback) {
return registerLifecycle(Lifecycle.titleClick, callback);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.titleClick, callback);
}, []);
}

export function useOptionMenuClick(callback: Callback) {
return registerLifecycle(Lifecycle.optionMenuClick, callback);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.optionMenuClick, callback);
}, []);
}

export function usePopMenuClick(callback: Callback) {
return registerLifecycle(Lifecycle.popMenuClick, callback);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.popMenuClick, callback);
}, []);
}

export function usePullIntercept(callback: Callback) {
return registerLifecycle(Lifecycle.pullIntercept, callback);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.pullIntercept, callback);
}, []);
}
2 changes: 1 addition & 1 deletion packages/remax/src/lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ export function callbackName(name: string) {
export function registerLifecycle(method: Lifecycle, callback: () => void) {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
currentPage.registerLifecycle(method, callback);
return currentPage.registerLifecycle(method, callback);
}

0 comments on commit 4fa5695

Please sign in to comment.