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;