Commit 3047b0d5 authored by Shen Chang's avatar Shen Chang

refactor(Add < KeepAlive > Components and delete keepAlive higher-order components):

parent 3e12c088
......@@ -6,7 +6,7 @@ import {
Link,
BrowserRouter as Router,
} from 'react-router-dom';
import {Provider} from '../../es';
import {Provider, KeepAlive} from '../../es';
import A from './views/A';
import B from './views/B';
import C from './views/C';
......@@ -58,18 +58,24 @@ class App extends React.Component {
<Route
path="/a"
render={() => (
<React.Fragment>
<A keepAlive={toggle} />
</React.Fragment>
<KeepAlive key="A" disabled={!toggle}>
<A />
</KeepAlive>
)}
/>
<Route
path="/b"
render={() => <B />}
render={() => (
<B />
)}
/>
<Route
path="/c"
render={() => <C />}
render={() => (
<KeepAlive key="C">
<C />
</KeepAlive>
)}
/>
</Switch>
</div>
......
import React from 'react';
import {keepAlive, bindLifecycle} from '../../../es';
import {bindLifecycle} from '../../../es';
@bindLifecycle
class Content extends React.Component {
......@@ -40,7 +40,7 @@ class Content extends React.Component {
}
}
@keepAlive()
@bindLifecycle
class Test extends React.Component {
state = {
index: 0,
......
import React from 'react';
import {keepAlive, bindLifecycle} from '../../../es';
import {bindLifecycle} from '../../../es';
@keepAlive()
@bindLifecycle
class B extends React.Component {
componentWillMount() {
console.log('B componentWillMount');
......
import React from 'react';
import {keepAlive} from '../../../es';
import {bindLifecycle} from '../../../es';
@bindLifecycle
class C extends React.Component {
componentWillMount() {
console.log('C componentWillMount');
......@@ -38,4 +39,4 @@ class C extends React.Component {
}
}
export default keepAlive()(C);
export default C;
{
"name": "react-keep-alive",
"version": "0.2.2",
"version": "0.3.0",
"description": "Package will allow components to maintain their status, to avoid repeated re-rendering.",
"author": "Shen Chang",
"homepage": "https://github.com/Sam618/react-keep-alive",
......
......@@ -3,7 +3,6 @@ import Comment from './Comment';
import {LIFECYCLE, ICache, ICacheItem} from './Provider';
import {warn} from '../utils/debug';
import findDOMNodeByFiberNode from '../utils/findDOMNodeByFiberNode';
import createUniqueIdentification from '../utils/createUniqueIdentification';
interface IConsumerProps {
children: React.ReactNode;
......@@ -19,9 +18,6 @@ class Consumer extends React.PureComponent<IConsumerProps> {
private identification: string = this.props.identification;
// This attribute is designed to prevent duplicates of the identification of KeepAlive components.
private key: string = createUniqueIdentification();
constructor(props: IConsumerProps, ...args: any) {
super(props, ...args);
const {cache, setCache, children} = props;
......@@ -43,7 +39,6 @@ class Consumer extends React.PureComponent<IConsumerProps> {
children,
keepAlive,
lifecycle: LIFECYCLE.MOUNTED,
key: this.key,
renderElement: this.renderElement,
activated: true,
});
......
import React from 'react';
import noop from '../utils/noop';
import keepAlive, {IKeepAliveComponentProps} from '../utils/keepAlive';
export const keepAliveDisplayName = '$$KeepAlive';
interface IKeepAliveProps extends IKeepAliveComponentProps {
key: string;
onActivate?: () => void;
onUnactivate?: () => void;
}
class KeepAlive extends React.PureComponent<IKeepAliveProps> {
public displayName = keepAliveDisplayName;
public static defaultProps = {
onActivate: noop,
onUnactivate: noop,
};
public componentDidActivate() {
(this.props as any).onActivate();
}
public componentWillUnactivate() {
(this.props as any).onUnactivate();
}
public render() {
return this.props.children;
}
}
export default keepAlive(KeepAlive) as React.ComponentClass<IKeepAliveProps>;
......@@ -7,7 +7,7 @@ import {warn} from '../utils/debug';
import createUniqueIdentification from '../utils/createUniqueIdentification';
import createStoreElement from '../utils/createStoreElement';
export const keepAliveProviderTypeName = 'KeepAliveProvider';
export const keepAliveProviderTypeName = '$$KeepAliveProvider';
export const START_MOUNTING_DOM = 'startMountingDOM';
export enum LIFECYCLE {
......@@ -20,7 +20,6 @@ export interface ICacheItem {
children: React.ReactNode;
keepAlive: boolean;
lifecycle: LIFECYCLE;
key?: string | null;
renderElement?: HTMLElement;
activated?: boolean;
ifStillActivate?: boolean;
......@@ -87,10 +86,6 @@ export default class KeepAliveProvider extends React.PureComponent<IKeepAlivePro
public setCache = (identification: string, value: ICacheItem) => {
const {cache, keys} = this;
const currentCache = cache[identification];
const key = currentCache && currentCache.key;
if (key && value.key && key !== (value.key as unknown)) {
warn('[React Keep Alive] Cached components have duplicates.');
}
if (!currentCache) {
keys.push(identification);
}
......@@ -101,6 +96,10 @@ export default class KeepAliveProvider extends React.PureComponent<IKeepAlivePro
this.forceUpdate();
}
public componentDidCatch() {
warn('[React Keep Alive] Cached components have duplicates. Please check the <KeepAlive> component of the key duplication!');
}
// private getMax = () => {
// return this.props.max ? parseInt(this.props.max) : null;
// }
......@@ -126,7 +125,6 @@ export default class KeepAliveProvider extends React.PureComponent<IKeepAlivePro
const {cache} = this;
this.cache[identification] = {
...cache[identification],
key: null,
activated: false,
lifecycle: LIFECYCLE.UNMOUNTED,
};
......
import Provider from './components/Provider';
import keepAlive from './utils/keepAlive';
import KeepAlive from './components/KeepAlive';
import bindLifecycle from './utils/bindLifecycle';
export {
Provider,
keepAlive,
KeepAlive,
bindLifecycle,
};
......@@ -5,7 +5,7 @@ import {COMMAND} from './keepAlive';
import withIdentificationContextConsumer from './withIdentificationContextConsumer';
import getDisplayName from './getDisplayName';
export default function bindLifecycle<P = any>(Component: React.ComponentType<P>) {
export default function bindLifecycle<P = any>(Component: React.ComponentClass<P>) {
const WrappedComponent = (Component as any).WrappedComponent || (Component as any).wrappedComponent || Component;
const {
......@@ -111,7 +111,7 @@ export default function bindLifecycle<P = any>(Component: React.ComponentType<P>
: null
),
);
const BindLifecycle = React.forwardRef((props, ref) => (
const BindLifecycle = React.forwardRef((props: P, ref) => (
<BindLifecycleHOC {...props} forwardRef={ref} />
));
......
import React from 'react';
import {keepAliveProviderTypeName} from '../components/Provider';
import {keepAliveDisplayName} from './keepAlive';
export default function getContextIdentificationByFiberNode(fiberNode: any) {
let globalKey: React.Key | null = null;
let typeNames = '';
function getPathsByFiberNode(fiberNode: any) {
if (!fiberNode) {
return '';
}
const {
type,
key,
index,
} = fiberNode;
const typeName = type && type.displayName;
if (typeName === keepAliveProviderTypeName) {
return '';
}
const joinName: string = getPathsByFiberNode(fiberNode.return);
if (type && type.displayName && type.displayName.indexOf(keepAliveDisplayName) !== -1) {
if (!globalKey) {
globalKey = key;
}
}
typeNames += typeName;
return `${key || index}${joinName}`;
}
const paths = getPathsByFiberNode(fiberNode);
return {
paths,
globalKey,
typeNames,
};
}
import React from 'react';
export default function getDisplayName(Component: React.ComponentType) {
return Component.displayName || Component.name || null;
return Component.displayName || Component.name || 'Component';
}
import {WithKeepAliveContextConsumerDisplayName} from './withKeepAliveContextConsumer';
export default function getKeyByFiberNode(fiberNode: any): string | null {
if (!fiberNode) {
return null;
}
const {
key,
type,
} = fiberNode;
if (type.displayName && type.displayName.indexOf(WithKeepAliveContextConsumerDisplayName) !== -1) {
return key;
}
return getKeyByFiberNode(fiberNode.return);
}
This diff is collapsed.
......@@ -11,17 +11,19 @@ export interface IIdentificationContextProps {
isExisted: () => boolean;
}
export interface IIdentificationContextComponentProps {
export interface IIdentificationContextConsumerComponentProps {
_identificationContextProps: IIdentificationContextProps;
}
export default function withIdentificationContextConsumer<P = any>(Component: React.ComponentType<IIdentificationContextComponentProps & P>) {
const NewComponent = (props: P) => (
export const withIdentificationContextConsumerDisplayName = 'withIdentificationContextConsumer';
export default function withIdentificationContextConsumer<P = any>(Component: React.ComponentType<IIdentificationContextConsumerComponentProps & P>) {
const WithIdentificationContextConsumer = (props: P) => (
<IdentificationContext.Consumer>
{(contextProps: IIdentificationContextProps) => <Component _identificationContextProps={contextProps} {...props} />}
</IdentificationContext.Consumer>
);
NewComponent.displayName = `withIdentificationContextConsumer(${getDisplayName(Component)})`;
return NewComponent;
WithIdentificationContextConsumer.displayName = `${withIdentificationContextConsumerDisplayName}(${getDisplayName(Component)})`;
return WithIdentificationContextConsumer;
}
......@@ -5,17 +5,19 @@ import getDisplayName from './getDisplayName';
type IKeepAliveContextProps = IKeepAliveProviderImpl & IKeepAliveProviderProps;
export interface IKeepAliveContextComponentProps {
export interface IKeepAliveContextConsumerComponentProps {
_keepAliveContextProps: IKeepAliveContextProps;
}
export default function withKeepAliveContextConsumer<P = any>(Component: React.ComponentType<IKeepAliveContextComponentProps & P>) {
const NewComponent = (props: P) => (
export const WithKeepAliveContextConsumerDisplayName = 'withKeepAliveContextConsumer';
export default function withKeepAliveContextConsumer<P = any>(Component: React.ComponentType<IKeepAliveContextConsumerComponentProps & P>) {
const WithKeepAliveContextConsumer = (props: P) => (
<KeepAliveContext.Consumer>
{(contextProps: IKeepAliveContextProps) => <Component _keepAliveContextProps={contextProps} {...props} />}
</KeepAliveContext.Consumer>
);
NewComponent.displayName = `withKeepAliveContextConsumer(${getDisplayName(Component)})`;
return NewComponent;
WithKeepAliveContextConsumer.displayName = `${WithKeepAliveContextConsumerDisplayName}(${getDisplayName(Component)})`;
return WithKeepAliveContextConsumer;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment