From 4680ddc009b1ecbc1bfe70594508301dd8888846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Tue, 1 Oct 2019 01:06:09 -0500 Subject: [PATCH] fix: Typography warning for `ref` error (#19074) * Revert "fix: Typography funtion compoent use Ref console log warning (#19066)" This reverts commit 3d378f2fd89a63caea7423d20b0f569ffc3c47a0. * fix: Typography warning for ref * not crash on react 15 * still use class if react15 * fix ts define * clean up * react 15 lock ref obj * Use rc-util findDOMNode instead --- components/_util/ref.ts | 17 ++++ components/typography/Base.tsx | 5 +- components/typography/Typography.tsx | 90 +++++++++++++------ components/typography/__tests__/index.test.js | 17 +++- 4 files changed, 96 insertions(+), 33 deletions(-) create mode 100644 components/_util/ref.ts diff --git a/components/_util/ref.ts b/components/_util/ref.ts new file mode 100644 index 0000000000..6221eb1041 --- /dev/null +++ b/components/_util/ref.ts @@ -0,0 +1,17 @@ +import React from 'react'; + +export function fillRef(ref: React.Ref, node: T) { + if (typeof ref === 'function') { + ref(node); + } else if (typeof ref === 'object' && ref && 'current' in ref) { + (ref as any).current = node; + } +} + +export function composeRef(...refs: React.Ref[]): React.Ref { + return (node: T) => { + refs.forEach(ref => { + fillRef(ref, node); + }); + }; +} diff --git a/components/typography/Base.tsx b/components/typography/Base.tsx index e0ac416a82..df5715d8f6 100644 --- a/components/typography/Base.tsx +++ b/components/typography/Base.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import classNames from 'classnames'; import { polyfill } from 'react-lifecycles-compat'; import toArray from 'rc-util/lib/Children/toArray'; +import findDOMNode from 'rc-util/lib/Dom/findDOMNode'; import copy from 'copy-to-clipboard'; import omit from 'omit.js'; import ResizeObserver from 'rc-resize-observer'; @@ -297,7 +298,7 @@ class Base extends React.Component diff --git a/components/typography/Typography.tsx b/components/typography/Typography.tsx index 599063225b..bc914de8b9 100644 --- a/components/typography/Typography.tsx +++ b/components/typography/Typography.tsx @@ -1,6 +1,8 @@ import * as React from 'react'; import classNames from 'classnames'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; +import warning from '../_util/warning'; +import { composeRef } from '../_util/ref'; export interface TypographyProps { id?: string; @@ -13,38 +15,68 @@ export interface TypographyProps { interface InternalTypographyProps extends TypographyProps { component?: string; + /** @deprecated Use `ref` directly if using React 16 */ setContentRef?: (node: HTMLElement) => void; } -class Typography extends React.Component { - renderTypography = ({ getPrefixCls }: ConfigConsumerProps) => { - const { - prefixCls: customizePrefixCls, - component = 'article', - className, - 'aria-label': ariaLabel, - setContentRef, - children, - ...restProps - } = this.props; - const Component = component as any; - const prefixCls = getPrefixCls('typography', customizePrefixCls); - - return ( - - {children} - - ); - }; - - render() { - return {this.renderTypography}; +const Typography: React.RefForwardingComponent<{}, InternalTypographyProps> = ( + { + prefixCls: customizePrefixCls, + component = 'article', + className, + 'aria-label': ariaLabel, + setContentRef, + children, + ...restProps + }, + ref, +) => { + let mergedRef = ref; + + if (setContentRef) { + warning(false, 'Typography', '`setContentRef` is deprecated. Please use `ref` instead.'); + mergedRef = composeRef(ref, setContentRef); } + + return ( + + {({ getPrefixCls }: ConfigConsumerProps) => { + const Component = component as any; + const prefixCls = getPrefixCls('typography', customizePrefixCls); + + return ( + + {children} + + ); + }} + + ); +}; + +let RefTypography; + +if (React.forwardRef) { + RefTypography = React.forwardRef(Typography); + RefTypography.displayName = 'Typography'; +} else { + class TypographyWrapper extends React.Component { + state = {}; + + render() { + return ; + } + } + + RefTypography = TypographyWrapper; } -export default Typography; +// es default export should use const instead of let +const ExportTypography = (RefTypography as unknown) as React.FC; + +export default ExportTypography; diff --git a/components/typography/__tests__/index.test.js b/components/typography/__tests__/index.test.js index 0f83d33e62..40b06491fc 100644 --- a/components/typography/__tests__/index.test.js +++ b/components/typography/__tests__/index.test.js @@ -6,6 +6,7 @@ import Title from '../Title'; import Paragraph from '../Paragraph'; import Base from '../Base'; // eslint-disable-line import/no-named-as-default import mountTest from '../../../tests/shared/mountTest'; +import Typography from '../Typography'; jest.mock('copy-to-clipboard'); @@ -94,10 +95,13 @@ describe('Typography', () => { }); it('connect children', () => { + const bamboo = 'Bamboo'; + const is = ' is '; + const wrapper = mount( - {'Bamboo'} - {' is '} + {bamboo} + {is} Little Light , @@ -237,4 +241,13 @@ describe('Typography', () => { }); }); }); + + it('warning if use setContentRef', () => { + function refFunc() {} + mount(); + + expect(errorSpy).toHaveBeenCalledWith( + 'Warning: [antd: Typography] `setContentRef` is deprecated. Please use `ref` instead.', + ); + }); });