diff --git a/src/slide-down/slide-down.test.tsx b/src/slide-down/slide-down.test.tsx index 578910f1d4..4d13cfed93 100644 --- a/src/slide-down/slide-down.test.tsx +++ b/src/slide-down/slide-down.test.tsx @@ -50,7 +50,8 @@ describe('slide-down', () => { ); - slideDownNode.instance().UNSAFE_componentWillReceiveProps({ ...props, isExpanded: true }); + slideDownNode.setProps({ isExpanded: true }); + expect(onAnimationStart).toHaveBeenCalled(); }); diff --git a/src/slide-down/slide-down.tsx b/src/slide-down/slide-down.tsx index 9712171ac6..e4a065f081 100644 --- a/src/slide-down/slide-down.tsx +++ b/src/slide-down/slide-down.tsx @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import React from 'react'; +import React, { createRef } from 'react'; import { DeepReadonly } from 'utility-types'; import { createCn } from 'bem-react-classname'; import { withTheme } from '../cn'; @@ -50,11 +50,17 @@ export type SlideDownProps = DeepReadonly<{ 'data-test-id'?: string; }>; + +type SlideDownState = { + height: number | string; + isHeightAuto: boolean; +} + /** * Компонент "расхлопа". * Позволяет скрывать и отображать контент. */ -export class SlideDown extends React.PureComponent { +export class SlideDown extends React.PureComponent { protected cn = createCn('slide-down'); state = { @@ -62,19 +68,21 @@ export class SlideDown extends React.PureComponent { isHeightAuto: this.props.isExpanded }; - private slideDown; - private slideDownContent; + private slideDown = createRef(); + private slideDownContent = createRef() + + componentDidUpdate(prevProps: SlideDownProps) { + const { isExpanded, onAnimationStart } = this.props; - // eslint-disable-next-line camelcase - UNSAFE_componentWillReceiveProps(nextProps) { - if (this.props.isExpanded !== nextProps.isExpanded) { - if (nextProps.isExpanded) { + if (prevProps.isExpanded !== isExpanded) { + if (isExpanded) { this.setHeightToContentHeight(); } else { this.setHeightToNull(); } - if (this.props.onAnimationStart) { - this.props.onAnimationStart(); + + if (onAnimationStart) { + onAnimationStart(); } } } @@ -88,16 +96,12 @@ export class SlideDown extends React.PureComponent { { height: this.getHeight() } } onTransitionEnd={ this.handleTransitionEnd } - ref={ (slideDown) => { - this.slideDown = slideDown; - } } + ref={ this.slideDown } data-test-id={ this.props['data-test-id'] } >
{ - this.slideDownContent = slideDownContent; - } } + ref={ this.slideDownContent } > { this.props.children }
@@ -105,7 +109,7 @@ export class SlideDown extends React.PureComponent { ); } - private handleTransitionEnd = (event) => { + private handleTransitionEnd = (event: React.TransitionEvent) => { if (event.propertyName === 'height' && this.props.isExpanded) { this.setAutoHeight(); } @@ -121,10 +125,12 @@ export class SlideDown extends React.PureComponent { } private setHeightToContentHeight() { - this.setState({ - isHeightAuto: false, - height: this.slideDownContent.offsetHeight - }); + if (this.slideDownContent.current) { + this.setState({ + isHeightAuto: false, + height: this.slideDownContent.current.offsetHeight + }); + } } private setHeightToNull() { @@ -133,10 +139,11 @@ export class SlideDown extends React.PureComponent { // Заставляем React перерисовать элемент this.forceUpdate(() => { // Заставляем браузер сделать reflow - this.slideDown.getBoundingClientRect(); - this.setState({ - height: 0 - }); + if (this.slideDown.current) { + this.slideDown.current.getBoundingClientRect(); + } + + this.setState({ height: 0 }); }); }