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

Commit

Permalink
fix: 修复在 App 上使用 Context 导致页面回调出错的问题
Browse files Browse the repository at this point in the history
close #256
  • Loading branch information
yesmeck committed Sep 27, 2019
1 parent 07b58b6 commit 56fcc2f
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 21 deletions.
5 changes: 5 additions & 0 deletions packages/remax/src/PageInstanceContext.ts
@@ -0,0 +1,5 @@
import * as React from 'react';

const PageInstanceContext = React.createContext(null);

export default PageInstanceContext;
29 changes: 24 additions & 5 deletions packages/remax/src/createPageWrapper.ts
@@ -1,6 +1,7 @@
import * as React from 'react';
import isClassComponent from './utils/isClassComponent';
import { Lifecycle, Callback, callbackName } from './lifecycle';
import PageInstanceContext from './PageInstanceContext';

export interface PageProps<Q = {}> {
location: {
Expand All @@ -13,7 +14,10 @@ export default function createPageWrapper(
query: object
) {
return class PageWrapper extends React.Component<{ page: any }> {
instance: any = null;
// 小程序 Page 实例
pageInstance: any = null;
// 页面组件的实例
pageComponentInstance: any = null;

callbacks = new Map<
string,
Expand All @@ -25,6 +29,8 @@ export default function createPageWrapper(
constructor(props: any) {
super(props);

this.bindPageInstance();

Object.keys(Lifecycle).forEach(phase => {
const callback = callbackName(phase);
(this as any)[callback] = (...args: any[]) => {
Expand All @@ -33,10 +39,19 @@ export default function createPageWrapper(
});
}

// 绑定小程序的 Page 实例
bindPageInstance() {
const pages = getCurrentPages();
this.pageInstance = pages[pages.length - 1];
}

callLifecycle(phase: string, ...args: any[]) {
const callback = callbackName(phase);
if (this.instance && typeof this.instance[callback] === 'function') {
return this.instance[callback](...args);
if (
this.pageComponentInstance &&
typeof this.pageComponentInstance[callback] === 'function'
) {
return this.pageComponentInstance[callback](...args);
}
}

Expand All @@ -48,10 +63,14 @@ export default function createPageWrapper(
};

if (isClassComponent(Page)) {
props.ref = (node: any) => (this.instance = node);
props.ref = (node: any) => (this.pageComponentInstance = node);
}

return React.createElement(Page, props);
return React.createElement(
PageInstanceContext.Provider,
{ value: this.pageInstance },
React.createElement(Page, props)
);
}
};
}
36 changes: 24 additions & 12 deletions packages/remax/src/hooks.ts
@@ -1,39 +1,46 @@
import { useLayoutEffect } from 'react';
import { useLayoutEffect, useContext } from 'react';
import { registerLifecycle, Lifecycle, Callback } from './lifecycle';
import PageInstanceContext from './PageInstanceContext';

export function useShow(callback: Callback) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.show, callback);
return registerLifecycle(pageInstance, Lifecycle.show, callback);
});
}

export function useReady(callback: Callback) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.ready, callback);
return registerLifecycle(pageInstance, Lifecycle.ready, callback);
});
}

export function useHide(callback: Callback) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.hide, callback);
return registerLifecycle(pageInstance, Lifecycle.hide, callback);
});
}

export function usePullDownRefresh(callback: Callback) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.pullDownRefresh, callback);
return registerLifecycle(pageInstance, Lifecycle.pullDownRefresh, callback);
});
}

export function useReachBottom(callback: Callback) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.reachBottom, callback);
return registerLifecycle(pageInstance, Lifecycle.reachBottom, callback);
});
}

export function usePageScroll(callback: Callback) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.pageScroll, callback);
return registerLifecycle(pageInstance, Lifecycle.pageScroll, callback);
});
}

Expand All @@ -44,31 +51,36 @@ export function useShareAppMessage(
webViewUrl: string;
}) => any
) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.shareAppMessage, callback);
return registerLifecycle(pageInstance, Lifecycle.shareAppMessage, callback);
});
}

export function useTitleClick(callback: Callback) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.titleClick, callback);
return registerLifecycle(pageInstance, Lifecycle.titleClick, callback);
});
}

export function useOptionMenuClick(callback: Callback) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.optionMenuClick, callback);
return registerLifecycle(pageInstance, Lifecycle.optionMenuClick, callback);
});
}

export function usePopMenuClick(callback: Callback) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.popMenuClick, callback);
return registerLifecycle(pageInstance, Lifecycle.popMenuClick, callback);
});
}

export function usePullIntercept(callback: Callback) {
const pageInstance = useContext(PageInstanceContext);
useLayoutEffect(() => {
return registerLifecycle(Lifecycle.pullIntercept, callback);
return registerLifecycle(pageInstance, Lifecycle.pullIntercept, callback);
});
}
10 changes: 6 additions & 4 deletions packages/remax/src/lifecycle.ts
Expand Up @@ -32,8 +32,10 @@ export function callbackName(name: string) {
return 'on' + capitalize(name);
}

export function registerLifecycle(method: Lifecycle, callback: Callback) {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
return currentPage.registerLifecycle(method, callback);
export function registerLifecycle(
page: any,
method: Lifecycle,
callback: Callback
) {
return page.registerLifecycle(method, callback);
}

0 comments on commit 56fcc2f

Please sign in to comment.