Commit a6c65439 authored by Shen Chang's avatar Shen Chang

refactor(KeepAlive): Asynchronous mount component

parent 1ed0cf2f
......@@ -6,11 +6,11 @@
<h1 align="center">React Keep Alive</h1>
<div align="center">
[![npm](https://img.shields.io/npm/v/react-keep-alive.svg?style=for-the-badge)](https://www.npmjs.com/package/react-keep-alive) [![Travis (.org)](https://img.shields.io/travis/Sam618/react-keep-alive.svg?style=for-the-badge)](https://travis-ci.org/Sam618/react-keep-alive.svg?branch=master) [![LICENSE](https://img.shields.io/npm/l/react-keep-alive.svg?style=for-the-badge)](https://github.com/Sam618/react-keep-alive/blob/master/LICENSE.MIT) [![LICENSE](https://img.shields.io/badge/license-Anti%20996-blue.svg?style=for-the-badge)](https://github.com/Sam618/react-keep-alive/blob/master/LICENSE.996ICU) [![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/react-keep-alive.svg?style=for-the-badge)](https://www.npmjs.com/package/react-keep-alive) [![downloads](https://img.shields.io/npm/dm/react-keep-alive.svg?style=for-the-badge)](https://www.npmjs.com/package/react-keep-alive) [![typescript](https://img.shields.io/badge/language-typescript-blue.svg?style=for-the-badge)](https://www.typescriptlang.org/) [![996.icu](https://img.shields.io/badge/link-996.icu-red.svg?style=for-the-badge)](https://996.icu)
<p><a href="https://nodei.co/npm/react-keep-alive/"><img src="https://nodei.co/npm/react-keep-alive.png?downloads=true&downloadRank=true&stars=true"></a></p>
<p>A component that maintains component state and avoids repeated re-rendering.</p>
<div style="width: 100px; text-align: left;">
......@@ -247,9 +247,14 @@ ReactDOM.render(
**Note**: If you want to use the **lifecycle**, wrap the components in a `bindLifecycle` high-level component.
### `bindLifecycle`
Components that pass this high-level component wrap will have the **correct** lifecycle, entering the component must trigger the `componentDidMount` lifecycle, and leaving will also trigger the `componentWillUnmount` lifecycle. Refer to this [example] (https://codesandbox.io/s/q1xprn1qq) for a better understanding, pay attention to open the console.
Components that pass this high-level component wrap will have the **correct** lifecycle, and we have added two additional lifecycles, `componentDidActivate` and `componentWillUnactivate`.
Lifecycle after adding:
![Lifecycle after adding](https://github.com/Sam618/react-keep-alive/raw/master/assets/lifecycle.png)
`componentDidActivate` will be executed once after the initial mount or from the unactivated state to the active state. although we see `componentDidActivate` after `componentDidUpdate` in the `Updating` phase, this does not mean `componentDidActivate` Always triggered.
The old version of ~~`componentDidActivate`~~ and ~~`componentWillUnactivate`~~ has been deleted, this is a component that is inevitably unaccustomed to the new life cycle, and was originally written with reference to Vue, but it is not entirely suitable for React.
At the same time, only one of the lifecycles of `componentWillUnactivate` and `componentWillUnmount` is triggered. `componentWillUnactivate` is executed when caching is required; `componentWillUnmount` is executed without caching.
#### Example
```JavaScript
......
......@@ -11,7 +11,7 @@
<p><a href="https://nodei.co/npm/react-keep-alive/"><img src="https://nodei.co/npm/react-keep-alive.png?downloads=true&downloadRank=true&stars=true"></a></p>
<p>一个保持组件状态并避免重复重渲染的组件。</p>
<div style="width: 100px; text-align: left;">
......@@ -250,9 +250,14 @@ ReactDOM.render(
**注意**:如果要使用 **生命周期**,请将组件包装在 `bindLifecycle` 高阶组件中。
### `bindLifecycle`
这个高阶组件包装的组件将具有 **正确的** 的生命周期,进入组件必定会触发 `componentDidMount` 生命周期,离开也必定会触发 `componentWillUnmount` 生命周期。参考这个 [例子](https://codesandbox.io/s/q1xprn1qq) 能够更好的理解,注意打开控制台。
这个高阶组件包装的组件将具有 **正确的** 的生命周期,并且我们添加了两个额外的生命周期 `componentDidActivate``componentWillUnactivate`
添加新的生命周期之后:
![Lifecycle after adding](https://github.com/Sam618/react-keep-alive/raw/master/assets/lifecycle.png)
`componentDidActivate` 将在组件刚挂载或从未激活状态变为激活状态时执行。虽然我们在 `Updating` 阶段的 `componentDidUpdate` 之后能够看到 `componentDidActivate`,但这并不意味着 `componentDidActivate` 总是被触发。
旧版本新增的 ~~`componentDidActivate`~~ 和 ~~`componentWillUnactivate`~~ 生命周期已经删除,这是考虑到了新增生命周期难免会不习惯,并且原来是参照 Vue 来写的组件,但其实并不完全适合 React
同时只能触发 `componentWillUnactivate``componentWillUnmount` 生命周期的其中之一。当需要缓存时执行 `componentWillUnactivate`,而 `componentWillUnmount` 在禁用缓存的情况下执行
#### 例子
```JavaScript
......
import React, {useState, useEffect} from 'react';
import React, {useState, useEffect, useRef} from 'react';
import {useKeepAliveEffect} from '../../../es';
import B from './B';
function Test() {
const [index, setIndex] = useState(0);
const divRef = useRef();
useKeepAliveEffect(() => {
console.log('activated', index);
console.log(divRef.current.offsetWidth);
const i = 0;
return () => {
......@@ -13,7 +16,8 @@ function Test() {
});
return (
<div>
<div>This is a.</div>
<div ref={divRef}>This is a.</div>
<B />
<button onClick={() => setIndex(index + 1)}>click me({index})</button>
</div>
);
......
......@@ -8,6 +8,7 @@ class B extends React.Component {
}
componentDidMount() {
console.log(this.ref.offsetWidth);
console.log('B componentDidMount');
}
......@@ -20,6 +21,7 @@ class B extends React.Component {
}
componentDidUpdate() {
console.log(this.ref.offsetWidth);
console.log('B componentDidUpdate');
}
......@@ -34,7 +36,7 @@ class B extends React.Component {
render() {
console.log('B render');
return (
<div>This is b.</div>
<div ref={ref => this.ref = ref}>This is b.</div>
);
}
}
......
......@@ -3,11 +3,20 @@ import {bindLifecycle} from '../../../es';
@bindLifecycle
class C extends React.Component {
state = {
value: false,
};
componentWillMount() {
console.log('C componentWillMount');
}
componentDidMount() {
setTimeout(() => {
this.setState({
value: true,
});
}, 1000);
console.log('C componentDidMount');
}
......@@ -34,7 +43,9 @@ class C extends React.Component {
render() {
console.log('C render');
return (
<div>This is c.</div>
<div>
{this.state.value ? <div>This is c.</div> : null}
</div>
);
}
}
......
{
"name": "react-keep-alive",
"version": "0.4.3",
"version": "1.2.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......@@ -7413,6 +7413,11 @@
}
}
},
"react-deep-force-update": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/react-deep-force-update/-/react-deep-force-update-2.1.3.tgz",
"integrity": "sha512-lqD4eHKVuB65RyO/hGbEST53E2/GPbcIPcFYyeW/p4vNngtH4G7jnKGlU6u1OqrFo0uNfIvwuBOg98IbLHlNEA=="
},
"react-dom": {
"version": "16.8.5",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.5.tgz",
......
{
"name": "react-keep-alive",
"version": "1.2.2",
"version": "2.0.0.alpha.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",
......@@ -37,7 +37,8 @@
"dependencies": {
"@types/js-md5": "^0.4.2",
"hoist-non-react-statics": "^3.3.0",
"js-md5": "^0.7.3"
"js-md5": "^0.7.3",
"react-deep-force-update": "^2.1.3"
},
"devDependencies": {
"@babel/cli": "^7.2.3",
......
import * as React from 'react';
import deepForceUpdate from 'react-deep-force-update';
interface IProps {
setMounted: any;
getMounted: any;
correctionPosition: any;
}
interface IState {
component: any;
}
export default class AsyncComponent extends React.Component<IProps, IState> {
public state = {
component: null,
};
public componentDidMount() {
const {children} = this.props;
Promise.resolve().then(() => this.setState({component: children}));
}
public componentDidUpdate() {
this.props.correctionPosition();
}
// Delayed update
// In order to be able to get real DOM data
public shouldComponentUpdate() {
if (!this.state.component) {
// If it is already mounted asynchronously, you don't need to do it again when you update it.
this.props.setMounted(false);
return true;
}
Promise.resolve().then(() => {
if (this.props.getMounted()) {
this.props.setMounted(false);
deepForceUpdate(this);
}
});
return false;
}
public render() {
return this.state.component;
}
}
import React from 'react';
import AsyncComponent from './AsyncComponent';
import {START_MOUNTING_DOM, LIFECYCLE} from './Provider';
import keepAlive, {COMMAND} from '../utils/keepAliveDecorator';
import changePositionByComment from '../utils/changePositionByComment';
......@@ -16,6 +17,18 @@ interface IKeepAliveInnerProps extends IKeepAliveProps {
class KeepAlive extends React.PureComponent<IKeepAliveInnerProps> {
private bindUnmount: (() => void) | null = null;
private bindUnactivate: (() => void) | null = null;
private unmounted = false;
private mounted = false;
private ref: null | Element = null;
private refNextSibling: null | ChildNode = null;
private childNodes: ChildNode[] = [];
public componentDidMount() {
const {
_container,
......@@ -24,6 +37,7 @@ class KeepAlive extends React.PureComponent<IKeepAliveInnerProps> {
notNeedActivate,
identification,
eventEmitter,
keepAlive,
} = _container;
notNeedActivate();
const cb = () => {
......@@ -32,6 +46,13 @@ class KeepAlive extends React.PureComponent<IKeepAliveInnerProps> {
eventEmitter.off([identification, START_MOUNTING_DOM], cb);
};
eventEmitter.on([identification, START_MOUNTING_DOM], cb);
if (keepAlive) {
this.componentDidActivate();
}
}
public componentDidActivate() {
// tslint-disable
}
public componentDidUpdate() {
......@@ -46,14 +67,24 @@ class KeepAlive extends React.PureComponent<IKeepAliveInnerProps> {
notNeedActivate();
this.mount();
this.listen();
this.unmounted = false;
this.componentDidActivate();
}
}
public componentWillUnmount() {
public componentWillUnactivate() {
this.unmount();
this.unlisten();
}
public componentWillUnmount() {
if (!this.unmounted) {
this.unmounted = true;
this.unmount();
this.unlisten();
}
}
private mount() {
const {
_container: {
......@@ -63,11 +94,33 @@ class KeepAlive extends React.PureComponent<IKeepAliveInnerProps> {
setLifecycle,
},
} = this.props;
this.setMounted(true);
const {renderElement} = cache[identification];
setLifecycle(LIFECYCLE.UPDATING);
changePositionByComment(identification, renderElement, storeElement);
}
private correctionPosition = () => {
if (this.ref && this.ref.parentNode && this.ref.nextSibling) {
const childNodes = this.ref.childNodes as any;
this.refNextSibling = this.ref.nextSibling;
for (const child of childNodes) {
this.childNodes.push(child);
this.ref.parentNode.insertBefore(child, this.ref.nextSibling);
}
this.ref.parentNode.removeChild(this.ref);
}
}
private retreatPosition = () => {
if (this.ref && this.refNextSibling && this.refNextSibling.parentNode) {
for (const child of this.childNodes) {
this.ref.appendChild(child);
}
this.refNextSibling.parentNode.insertBefore(this.ref, this.refNextSibling);
}
}
private unmount() {
const {
_container: {
......@@ -79,6 +132,7 @@ class KeepAlive extends React.PureComponent<IKeepAliveInnerProps> {
} = this.props;
const {renderElement, ifStillActivate, reactivate} = cache[identification];
setLifecycle(LIFECYCLE.UNMOUNTED);
this.retreatPosition();
changePositionByComment(identification, storeElement, renderElement);
if (ifStillActivate) {
reactivate();
......@@ -96,6 +150,10 @@ class KeepAlive extends React.PureComponent<IKeepAliveInnerProps> {
[identification, COMMAND.CURRENT_UNMOUNT],
this.bindUnmount = this.componentWillUnmount.bind(this),
);
eventEmitter.on(
[identification, COMMAND.CURRENT_UNACTIVATE],
this.bindUnactivate = this.componentWillUnactivate.bind(this),
);
}
private unlisten() {
......@@ -106,10 +164,31 @@ class KeepAlive extends React.PureComponent<IKeepAliveInnerProps> {
},
} = this.props;
eventEmitter.off([identification, COMMAND.CURRENT_UNMOUNT], this.bindUnmount);
eventEmitter.off([identification, COMMAND.CURRENT_UNACTIVATE], this.bindUnactivate);
}
private setMounted = (value: boolean) => {
this.mounted = value;
}
private getMounted = () => {
return this.mounted;
}
public render() {
return this.props.children;
// The purpose of this div is to not report an error when moving the DOM,
// so you need to remove this div later.
return (
<div ref={ref => this.ref = ref}>
<AsyncComponent
setMounted={this.setMounted}
getMounted={this.getMounted}
correctionPosition={this.correctionPosition}
>
{this.props.children}
</AsyncComponent>
</div>
);
}
}
......
......@@ -12,7 +12,10 @@ export default function bindLifecycle<P = any>(Component: React.ComponentClass<P
const {
componentDidMount = noop,
componentDidUpdate = noop,
componentDidActivate = noop,
componentWillUnactivate = noop,
componentWillUnmount = noop,
shouldComponentUpdate = noop,
} = WrappedComponent.prototype;
WrappedComponent.prototype.componentDidMount = function () {
......@@ -22,12 +25,25 @@ export default function bindLifecycle<P = any>(Component: React.ComponentClass<P
_container: {
identification,
eventEmitter,
activated,
},
keepAlive,
} = this.props;
this._unmounted = false;
// Determine whether to execute the componentDidActivate life cycle of the current component based on the activation state of the KeepAlive components
if (!activated && keepAlive !== false) {
componentDidActivate.call(this);
}
eventEmitter.on(
[identification, COMMAND.ACTIVATE],
this._bindActivate = () => this._needActivate = true,
true,
);
eventEmitter.on(
[identification, COMMAND.MOUNT],
this._bindMount = () => this._needActivate = true,
[identification, COMMAND.UNACTIVATE],
this._bindUnactivate = () => {
componentWillUnactivate.call(this);
this._unmounted = false;
},
true,
);
eventEmitter.on(
......@@ -39,13 +55,20 @@ export default function bindLifecycle<P = any>(Component: React.ComponentClass<P
true,
);
};
WrappedComponent.prototype.componentDidUpdate = function (...args: any) {
// In order to be able to re-update after transferring the DOM, we need to block the first update.
WrappedComponent.prototype.shouldComponentUpdate = function (...args: any) {
if (this._needActivate) {
return false;
}
return shouldComponentUpdate.call(this, ...args) || true;
};
WrappedComponent.prototype.componentDidUpdate = function () {
componentDidUpdate.call(this);
if (this._needActivate) {
this._needActivate = false;
this._unmounted = false;
componentDidMount.call(this);
} else {
componentDidUpdate.apply(this, args);
componentDidActivate.call(this);
}
};
WrappedComponent.prototype.componentWillUnmount = function () {
......@@ -59,8 +82,12 @@ export default function bindLifecycle<P = any>(Component: React.ComponentClass<P
},
} = this.props;
eventEmitter.off(
[identification, COMMAND.MOUNT],
this._bindMount,
[identification, COMMAND.ACTIVATE],
this._bindActivate,
);
eventEmitter.off(
[identification, COMMAND.UNACTIVATE],
this._bindUnactivate,
);
eventEmitter.off(
[identification, COMMAND.UNMOUNT],
......@@ -74,6 +101,8 @@ export default function bindLifecycle<P = any>(Component: React.ComponentClass<P
_identificationContextProps: {
identification,
eventEmitter,
activated,
keepAlive,
},
...wrapperProps
}) => {
......@@ -88,6 +117,8 @@ export default function bindLifecycle<P = any>(Component: React.ComponentClass<P
_container={{
identification,
eventEmitter,
activated,
keepAlive,
}}
/>
);
......
......@@ -3,12 +3,7 @@ import {prefix} from './createUniqueIdentification';
export default function createStoreElement(): HTMLElement {
const keepAliveDOM = document.createElement('div');
keepAliveDOM.dataset.type = prefix;
keepAliveDOM.style.visibility = 'hidden';
keepAliveDOM.style.opacity = '0';
keepAliveDOM.style.position = 'absolute';
keepAliveDOM.style.top = '0';
keepAliveDOM.style.left = '0';
keepAliveDOM.style.zIndex = '-1';
keepAliveDOM.style.display = 'none';
document.body.appendChild(keepAliveDOM);
return keepAliveDOM;
}
......@@ -12,9 +12,11 @@ import shallowEqual from './shallowEqual';
import getKeepAlive from './getKeepAlive';
export enum COMMAND {
UNACTIVATE = 'unactivate',
UNMOUNT = 'unmount',
MOUNT = 'mount',
ACTIVATE = 'activate',
CURRENT_UNMOUNT = 'current_unmount',
CURRENT_UNACTIVATE = 'current_unactivate',
}
interface IListenUpperKeepAliveContainerProps extends IIdentificationContextConsumerComponentProps, IKeepAliveContextConsumerComponentProps {
......@@ -29,6 +31,7 @@ interface IListenUpperKeepAliveContainerState {
interface ITriggerLifecycleContainerProps extends IKeepAliveContextConsumerComponentProps {
propKey: string;
keepAlive: boolean;
getCombinedKeepAlive: () => boolean;
}
/**
......@@ -43,6 +46,8 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
class TriggerLifecycleContainer extends React.PureComponent<ITriggerLifecycleContainerProps> {
private identification: string;
private activated = false;
private ifStillActivate = false;
// Let the lifecycle of the cached component be called normally.
......@@ -63,6 +68,9 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
}
public componentDidMount() {
if (!this.ifStillActivate) {
this.activate();
}
const {
keepAlive,
_keepAliveContextProps: {
......@@ -71,18 +79,39 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
} = this.props;
if (keepAlive) {
this.needActivate = true;
eventEmitter.emit([this.identification, COMMAND.MOUNT]);
eventEmitter.emit([this.identification, COMMAND.ACTIVATE]);
}
}
public componentDidCatch() {
if (!this.activated) {
this.activate();
}
}
public componentWillUnmount() {
const {
getCombinedKeepAlive,
_keepAliveContextProps: {
eventEmitter,
isExisted,
},
} = this.props;
eventEmitter.emit([this.identification, COMMAND.CURRENT_UNMOUNT]);
eventEmitter.emit([this.identification, COMMAND.UNMOUNT]);
const keepAlive = getCombinedKeepAlive();
if (!keepAlive || !isExisted()) {
eventEmitter.emit([this.identification, COMMAND.CURRENT_UNMOUNT]);
eventEmitter.emit([this.identification, COMMAND.UNMOUNT]);
}
// When the Provider components are unmounted, the cache is not needed,
// so you don't have to execute the componentWillUnactivate lifecycle.
if (keepAlive && isExisted()) {
eventEmitter.emit([this.identification, COMMAND.CURRENT_UNACTIVATE]);
eventEmitter.emit([this.identification, COMMAND.UNACTIVATE]);
}
}
private activate = () => {
this.activated = true;
}
private reactivate = () => {
......@@ -110,6 +139,7 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
const {
propKey,
keepAlive,
getCombinedKeepAlive,
_keepAliveContextProps: {
isExisted,
storeElement,
......@@ -137,6 +167,7 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
const {
isNeedActivate,
notNeedActivate,
activated,
getLifecycle,
setLifecycle,
identification,
......@@ -156,6 +187,7 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
identification,
eventEmitter,
keepAlive,
activated,
getLifecycle,
isExisted,
}}
......@@ -169,6 +201,7 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
eventEmitter,
identification,
storeElement,
keepAlive,
cache,
}}
/>
......@@ -180,11 +213,15 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
}
class ListenUpperKeepAliveContainer extends React.Component<IListenUpperKeepAliveContainerProps, IListenUpperKeepAliveContainerState> {
private combinedKeepAlive: boolean;
public state = {
activated: true,
};
private mount: () => void;
private activate: () => void;
private unactivate: () => void;
private unmount: () => void;
......@@ -228,8 +265,13 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
return;
}
eventEmitter.on(
[identification, COMMAND.MOUNT],
this.mount = () => this.setState({activated: true}),
[identification, COMMAND.ACTIVATE],
this.activate = () => this.setState({activated: true}),
true,
);
eventEmitter.on(
[identification, COMMAND.UNACTIVATE],
this.unactivate = () => this.setState({activated: false}),
true,
);
eventEmitter.on(
......@@ -244,10 +286,15 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
if (!identification) {
return;
}
eventEmitter.off([identification, COMMAND.MOUNT], this.mount);
eventEmitter.off([identification, COMMAND.ACTIVATE], this.activate);
eventEmitter.off([identification, COMMAND.UNACTIVATE], this.unactivate);
eventEmitter.off([identification, COMMAND.UNMOUNT], this.unmount);
}
private getCombinedKeepAlive = () => {
return this.combinedKeepAlive;
}
public render() {
const {
_identificationContextProps: {
......@@ -274,7 +321,7 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
return null;
}
const newKeepAlive = getKeepAlive(propKey, include, exclude, disabled);
const combinedKeepAlive = getLifecycle === undefined || getLifecycle() === LIFECYCLE.UPDATING
this.combinedKeepAlive = getLifecycle === undefined || getLifecycle() === LIFECYCLE.UPDATING
? newKeepAlive
: identification
? upperKeepAlive && newKeepAlive
......@@ -285,7 +332,8 @@ export default function keepAliveDecorator<P = any>(Component: React.ComponentTy
{...wrapperProps}
key={propKey}
propKey={propKey}
keepAlive={combinedKeepAlive}
keepAlive={this.combinedKeepAlive}
getCombinedKeepAlive={this.getCombinedKeepAlive}
/>
)
: null;
......
import React, {useEffect, useContext, useRef} from 'react';
import React, {useEffect, useContext, useRef, useState} from 'react';
import {warn} from './debug';
import {COMMAND} from './keepAliveDecorator';
import IdentificationContext, {IIdentificationContextProps} from '../contexts/IdentificationContext';
......@@ -14,18 +14,32 @@ export default function useKeepAliveEffect(effect: React.EffectCallback) {
const effectRef: React.MutableRefObject<React.EffectCallback> = useRef(effect);
effectRef.current = effect;
useEffect(() => {
let bindMount: (() => void) | null = null;
let bindActivate: (() => void) | null = null;
let bindUnactivate: (() => void) | null = null;
let bindUnmount: (() => void) | null = null;
let effectResult = effectRef.current();
let unmounted = false;
eventEmitter.on(
[identification, COMMAND.MOUNT],
bindMount = () => {
effectResult = effectRef.current();
[identification, COMMAND.ACTIVATE],
bindActivate = () => {
// Delayed update
Promise.resolve().then(() => {
effectResult = effectRef.current();
});
unmounted = false;
},
true,
);
eventEmitter.on(
[identification, COMMAND.UNACTIVATE],
bindUnactivate = () => {
if (effectResult) {
effectResult();
unmounted = true;
}
},
true,
);
eventEmitter.on(
[identification, COMMAND.UNMOUNT],
bindUnmount = () => {
......@@ -41,8 +55,12 @@ export default function useKeepAliveEffect(effect: React.EffectCallback) {
effectResult();
}
eventEmitter.off(
[identification, COMMAND.MOUNT],
bindMount,
[identification, COMMAND.ACTIVATE],
bindActivate,
);
eventEmitter.off(
[identification, COMMAND.UNACTIVATE],
bindUnactivate,
);
eventEmitter.off(
[identification, COMMAND.UNMOUNT],
......
......@@ -6,6 +6,7 @@
"rules": {
"max-line-length": false,
"no-console": false,
"no-debugger": false,
"quotemark": [true, "single", "jsx-double"],
"trailing-comma": [true, {"multiline": "ignore", "singleline": "never"}],
"ordered-imports": false,
......
declare module "react-deep-force-update" {
export default function deepForceUpdate(instance: any, shouldUpdate?: Function, onUpdate?: Function): void;
}
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