[change] modernize Text

Rewrite Text to use function components and hooks.
This commit is contained in:
Nicolas Gallagher
2020-02-04 13:19:03 -08:00
parent 2724ca0293
commit 35236a3cc2
3 changed files with 68 additions and 63 deletions
+56 -52
View File
@@ -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<TextProps> {
static displayName = 'Text';
const Text = forwardRef<TextProps, *>((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 (
<TextAncestorContext.Consumer>
{hasTextAncestor => {
const element = this.renderText(hasTextAncestor);
return hasTextAncestor ? (
element
) : (
<TextAncestorContext.Provider value={true}>{element}</TextAncestorContext.Provider>
);
}}
</TextAncestorContext.Consumer>
);
}
_createEnterHandler(fn) {
function createEnterHandler(fn) {
return e => {
if (e.keyCode === 13) {
fn && fn(e);
@@ -77,13 +56,38 @@ class Text extends React.Component<TextProps> {
};
}
_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
) : (
<TextAncestorContext.Provider value={true}>{element}</TextAncestorContext.Provider>
);
});
Text.displayName = 'Text';
const classes = css.create({
text: {
@@ -127,4 +131,4 @@ const styles = StyleSheet.create({
}
});
export default applyLayout(applyNativeMethods(Text));
export default Text;
+11 -10
View File
@@ -37,7 +37,7 @@ function createHitSlopElement(hitSlop) {
}
const View = forwardRef<ViewProps, *>((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<ViewProps, *>((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<ViewProps, *>((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);
});
+1 -1
View File
@@ -17,7 +17,7 @@ import { useImperativeHandle, useRef } from 'react';
export default function usePlatformMethods(
hostRef: ElementRef<any>,
ref: ElementRef<any>,
classList: Array<string>,
classList: Array<boolean | string>,
style: GenericStyleProp<any>
) {
const previousStyle = useRef(null);