From 35236a3cc2782bc0cce90faf42a97cb9dec2d392 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Tue, 4 Feb 2020 13:19:03 -0800 Subject: [PATCH] [change] modernize Text Rewrite Text to use function components and hooks. --- .../src/exports/Text/index.js | 108 +++++++++--------- .../src/exports/View/index.js | 21 ++-- .../src/hooks/usePlatformMethods.js | 2 +- 3 files changed, 68 insertions(+), 63 deletions(-) diff --git a/packages/react-native-web/src/exports/Text/index.js b/packages/react-native-web/src/exports/Text/index.js index 5f79e866..6de8f66d 100644 --- a/packages/react-native-web/src/exports/Text/index.js +++ b/packages/react-native-web/src/exports/Text/index.js @@ -10,66 +10,45 @@ import type { TextProps } from './types'; -import applyLayout from '../../modules/applyLayout'; -import applyNativeMethods from '../../modules/applyNativeMethods'; import createElement from '../createElement'; import css from '../StyleSheet/css'; import filterSupportedProps from '../View/filterSupportedProps'; -import React from 'react'; +import setAndForwardRef from '../../modules/setAndForwardRef'; +import useElementLayout from '../../hooks/useElementLayout'; +import usePlatformMethods from '../../hooks/usePlatformMethods'; +import React, { forwardRef, useContext, useRef } from 'react'; import StyleSheet from '../StyleSheet'; import TextAncestorContext from './TextAncestorContext'; -class Text extends React.Component { - static displayName = 'Text'; +const Text = forwardRef((props, ref) => { + const { dir, forwardedRef, numberOfLines, onLayout, onPress, selectable } = props; - renderText(hasTextAncestor) { - const { dir, forwardedRef, numberOfLines, onPress, selectable, style } = this.props; - - const supportedProps = filterSupportedProps(this.props); - - if (onPress) { - supportedProps.accessible = true; - supportedProps.onClick = this._createPressHandler(onPress); - supportedProps.onKeyDown = this._createEnterHandler(onPress); + const hasTextAncestor = useContext(TextAncestorContext); + const hostRef = useRef(null); + const setRef = setAndForwardRef({ + getForwardedRef: () => forwardedRef, + setLocalRef: c => { + hostRef.current = c; } + }); - supportedProps.classList = [ - classes.text, - hasTextAncestor === true && classes.textHasAncestor, - numberOfLines === 1 && classes.textOneLine, - numberOfLines != null && numberOfLines > 1 && classes.textMultiLine - ]; - // allow browsers to automatically infer the language writing direction - supportedProps.dir = dir !== undefined ? dir : 'auto'; - supportedProps.ref = forwardedRef; - supportedProps.style = [ - style, - numberOfLines != null && numberOfLines > 1 && { WebkitLineClamp: numberOfLines }, - selectable === false && styles.notSelectable, - onPress && styles.pressable - ]; + const classList = [ + classes.text, + hasTextAncestor === true && classes.textHasAncestor, + numberOfLines === 1 && classes.textOneLine, + numberOfLines != null && numberOfLines > 1 && classes.textMultiLine + ]; + const style = [ + props.style, + numberOfLines != null && numberOfLines > 1 && { WebkitLineClamp: numberOfLines }, + selectable === false && styles.notSelectable, + onPress && styles.pressable + ]; - const component = hasTextAncestor ? 'span' : 'div'; + useElementLayout(hostRef, onLayout); + usePlatformMethods(hostRef, ref, classList, style); - return createElement(component, supportedProps); - } - - render() { - return ( - - {hasTextAncestor => { - const element = this.renderText(hasTextAncestor); - return hasTextAncestor ? ( - element - ) : ( - {element} - ); - }} - - ); - } - - _createEnterHandler(fn) { + function createEnterHandler(fn) { return e => { if (e.keyCode === 13) { fn && fn(e); @@ -77,13 +56,38 @@ class Text extends React.Component { }; } - _createPressHandler(fn) { + function createPressHandler(fn) { return e => { e.stopPropagation(); fn && fn(e); }; } -} + + const supportedProps = filterSupportedProps(props); + + if (onPress) { + supportedProps.accessible = true; + supportedProps.onClick = createPressHandler(onPress); + supportedProps.onKeyDown = createEnterHandler(onPress); + } + + supportedProps.classList = classList; + // allow browsers to automatically infer the language writing direction + supportedProps.dir = dir !== undefined ? dir : 'auto'; + supportedProps.ref = setRef; + supportedProps.style = style; + + const component = hasTextAncestor ? 'span' : 'div'; + const element = createElement(component, supportedProps); + + return hasTextAncestor ? ( + element + ) : ( + {element} + ); +}); + +Text.displayName = 'Text'; const classes = css.create({ text: { @@ -127,4 +131,4 @@ const styles = StyleSheet.create({ } }); -export default applyLayout(applyNativeMethods(Text)); +export default Text; diff --git a/packages/react-native-web/src/exports/View/index.js b/packages/react-native-web/src/exports/View/index.js index d37a6732..f015e2e8 100644 --- a/packages/react-native-web/src/exports/View/index.js +++ b/packages/react-native-web/src/exports/View/index.js @@ -37,7 +37,7 @@ function createHitSlopElement(hitSlop) { } const View = forwardRef((props, ref) => { - const { forwardedRef, hitSlop, onLayout, style, ...rest } = props; + const { children, forwardedRef, hitSlop, onLayout } = props; if (process.env.NODE_ENV !== 'production') { React.Children.toArray(props.children).forEach(item => { @@ -47,10 +47,8 @@ const View = forwardRef((props, ref) => { }); } - const classList = [classes.view]; const hasTextAncestor = useContext(TextAncestorContext); const hostRef = useRef(null); - const setRef = setAndForwardRef({ getForwardedRef: () => forwardedRef, setLocalRef: c => { @@ -58,19 +56,22 @@ const View = forwardRef((props, ref) => { } }); + const classList = [classes.view]; + const style = StyleSheet.compose( + hasTextAncestor && styles.inline, + props.style + ); + useElementLayout(hostRef, onLayout); usePlatformMethods(hostRef, ref, classList, style); - const supportedProps = filterSupportedProps(rest); + const supportedProps = filterSupportedProps(props); supportedProps.children = hitSlop - ? React.Children.toArray([createHitSlopElement(hitSlop), props.children]) - : props.children; + ? React.Children.toArray([createHitSlopElement(hitSlop), children]) + : children; supportedProps.classList = classList; supportedProps.ref = setRef; - supportedProps.style = StyleSheet.compose( - hasTextAncestor && styles.inline, - style - ); + supportedProps.style = style; return createElement('div', supportedProps); }); diff --git a/packages/react-native-web/src/hooks/usePlatformMethods.js b/packages/react-native-web/src/hooks/usePlatformMethods.js index b6c543fb..02e2457d 100644 --- a/packages/react-native-web/src/hooks/usePlatformMethods.js +++ b/packages/react-native-web/src/hooks/usePlatformMethods.js @@ -17,7 +17,7 @@ import { useImperativeHandle, useRef } from 'react'; export default function usePlatformMethods( hostRef: ElementRef, ref: ElementRef, - classList: Array, + classList: Array, style: GenericStyleProp ) { const previousStyle = useRef(null);