From e4c01d72c1b685315a4d72bed2a77ae2bf95f853 Mon Sep 17 00:00:00 2001 From: Apoorv Kansal Date: Thu, 15 Jul 2021 02:06:51 +0530 Subject: [PATCH] Conditionally Rendering Children only if animation is running --- src/__tests__/index.js | 41 +++++++++++++++++++++++++++++++++++++++++ src/index.js | 40 ++++++++++++++++++++++++++++------------ 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/__tests__/index.js b/src/__tests__/index.js index e505e1c..061e67e 100644 --- a/src/__tests__/index.js +++ b/src/__tests__/index.js @@ -260,4 +260,45 @@ describe('index', () => { expect(confettiAnimatedView.props.renderToHardwareTextureAndroid).toEqual(true); }); + + it('should not render children if autoStart is disabled', () => { + const origin = {x: -10, y: 0}; + const count = 10; + + const component = renderer.create( + + ); + expect(component.toJSON()).toBeNull(); + }); + + it('should render children when started programatically and unmount after animation', ()=>{ + const ref = jest.fn<[ConfettiCannon | null], void>(); + const count = 10 + const component = renderer.create( + + ); + + const [confettiCannon] = ref.mock.calls[0]; + + confettiCannon && confettiCannon.start(); + const items = component.root.findAll(el => el.props.testID && el.props.testID.match(/confetti/g)); + expect(items.length).toEqual(count); + + confettiCannon && confettiCannon.stop(); + + const itemsAfterStrop = component.root.findAll(el => el.props.testID && el.props.testID.match(/confetti/g)); + expect(itemsAfterStrop.length).toEqual(count); + + confettiCannon && confettiCannon.resume(); + + jest.advanceTimersByTime(DEFAULT_EXPLOSION_SPEED + DEFAULT_FALL_SPEED); + + expect(component.toJSON()).toBeNull(); + }) + }); diff --git a/src/index.js b/src/index.js index 7092e70..53a0b68 100644 --- a/src/index.js +++ b/src/index.js @@ -40,7 +40,8 @@ type Item = {| |}; type State = {| - items: Array + items: Array, + showItems : boolean |}; export const TOP_MIN = 0.7; @@ -63,7 +64,8 @@ export const DEFAULT_FALL_SPEED = 3000; class Explosion extends React.PureComponent { props: Props; state: State = { - items: [] + items: [], + showItems : false }; start: () => void; resume: () => void; @@ -88,7 +90,13 @@ class Explosion extends React.PureComponent { const { autoStart = true, autoStartDelay = 0 } = this.props; if (autoStart) { - setTimeout(this.start, autoStartDelay); + // Set Timeout with zero delay is not instantenous. Waits for a cycle + if(autoStartDelay){ + setTimeout(this.start, autoStartDelay); + } + else{ + this.start(); + } } }; @@ -130,14 +138,17 @@ class Explosion extends React.PureComponent { }; start = (resume?: boolean = false) => { - const { - explosionSpeed = DEFAULT_EXPLOSION_SPEED, - fallSpeed = DEFAULT_FALL_SPEED, + this.setState({ + showItems:true, + }, ()=>{ + const { + explosionSpeed = DEFAULT_EXPLOSION_SPEED, + fallSpeed = DEFAULT_FALL_SPEED, onAnimationStart, onAnimationResume, onAnimationEnd } = this.props; - + if (resume) { onAnimationResume && onAnimationResume(); } else { @@ -155,16 +166,19 @@ class Explosion extends React.PureComponent { easing: Easing.quad, useNativeDriver: true }), - ]); - + ]); onAnimationStart && onAnimationStart(); - } - + } + this.sequence && this.sequence.start(({finished}: EndResult) => { if (finished) { onAnimationEnd && onAnimationEnd(); + this.setState({ + showItems:false + }) } }); + }) }; resume = () => this.start(true); @@ -181,7 +195,9 @@ class Explosion extends React.PureComponent { const { origin, fadeOut } = this.props; const { items } = this.state; const { height, width } = Dimensions.get('window'); - + if(!this.state.showItems){ + return null; + } return ( {items.map((item: Item, index: number) => {