diff --git a/components/affix/__tests__/Affix.test.js b/components/affix/__tests__/Affix.test.js
index d565494d71..1ce47ecd65 100644
--- a/components/affix/__tests__/Affix.test.js
+++ b/components/affix/__tests__/Affix.test.js
@@ -1,6 +1,7 @@
import React from 'react';
import { mount } from 'enzyme';
import Affix from '..';
+import { getObserverEntities } from '../utils';
import Button from '../../button';
const events = {};
@@ -128,14 +129,37 @@ describe('Affix Render', () => {
expect(wrapper.instance().affix.state.affixStyle.top).toBe(10);
});
- it('updatePosition when target changed', () => {
- const container = '
';
- const getTarget = () => container;
- wrapper = mount();
- wrapper.setProps({ target: null });
- expect(wrapper.instance().state.status).toBe(0);
- expect(wrapper.instance().state.affixStyle).toBe(undefined);
- expect(wrapper.instance().state.placeholderStyle).toBe(undefined);
+ describe('updatePosition when target changed', () => {
+ it('function change', () => {
+ document.body.innerHTML = '';
+ const container = document.querySelector('#id');
+ const getTarget = () => container;
+ wrapper = mount();
+ wrapper.setProps({ target: null });
+ expect(wrapper.instance().state.status).toBe(0);
+ expect(wrapper.instance().state.affixStyle).toBe(undefined);
+ expect(wrapper.instance().state.placeholderStyle).toBe(undefined);
+ });
+
+ it('instance change', () => {
+ const getObserverLength = () => Object.keys(getObserverEntities()).length;
+
+ const container = document.createElement('div');
+ document.body.appendChild(container);
+ let target = container;
+
+ const originLength = getObserverLength();
+ const getTarget = () => target;
+ wrapper = mount();
+ jest.runAllTimers();
+
+ expect(getObserverLength()).toBe(originLength + 1);
+ target = null;
+ wrapper.setProps({});
+ wrapper.update();
+ jest.runAllTimers();
+ expect(getObserverLength()).toBe(originLength);
+ });
});
it('updatePosition when size changed', () => {
diff --git a/components/affix/index.tsx b/components/affix/index.tsx
index bdac32f5c7..94cebea05b 100644
--- a/components/affix/index.tsx
+++ b/components/affix/index.tsx
@@ -41,6 +41,8 @@ export interface AffixState {
placeholderStyle?: React.CSSProperties;
status: AffixStatus;
lastAffix: boolean;
+
+ prevTarget: Window | HTMLElement | null;
}
class Affix extends React.Component {
@@ -51,6 +53,7 @@ class Affix extends React.Component {
state: AffixState = {
status: AffixStatus.None,
lastAffix: false,
+ prevTarget: null,
};
placeholderNode: HTMLDivElement;
@@ -72,14 +75,22 @@ class Affix extends React.Component {
}
componentDidUpdate(prevProps: AffixProps) {
+ const { prevTarget } = this.state;
const { target } = this.props;
- if (prevProps.target !== target) {
+ let newTarget = null;
+ if (target) {
+ newTarget = target() || null;
+ }
+
+ if (prevTarget !== newTarget) {
removeObserveTarget(this);
- if (target) {
- addObserveTarget(target(), this);
+ if (newTarget) {
+ addObserveTarget(newTarget, this);
// Mock Event object.
this.updatePosition({} as Event);
}
+
+ this.setState({ prevTarget: newTarget });
}
if (
diff --git a/components/affix/utils.ts b/components/affix/utils.ts
index 60bad06ad1..5a33e4b753 100644
--- a/components/affix/utils.ts
+++ b/components/affix/utils.ts
@@ -20,6 +20,11 @@ interface ObserverEntity {
let observerEntities: ObserverEntity[] = [];
+export function getObserverEntities() {
+ // Only used in test env. Can be removed if refactor.
+ return observerEntities;
+}
+
export function addObserveTarget(target: HTMLElement | Window | null, affix: Affix): void {
if (!target) return;