Tips Componente Text de React Native

Tips Componente Text de React Native

Una de las particularidades de React Native a diferencia de React en la Web es el uso de exclusivo de la etiqueta o componente predeterminado para el tratamiento de textos, pero este en ocasiones genera ciertas particularidades.

Empecemos con el primer ejemplo de antemano avisando también que por defecto el manejo de estilos en cuanto posicionamiento en React Native se usa Flexbox y uso posición natural es columnas en lugar de filas(rows) como en la web

El ejemplo es el siguiente: se tiene un contenedor donde se agrupan distintas propiedades de texto así luce el código

<View style={styles.avatarTextContainer}>
          <Text fontWeight={'bold'} fontSize={'subheading'}>
            {fullName}
          </Text>

          <Text
            testID="repositoryDescription"
            style={styles.textDescription}
            color="textSecondary"
          >
            {description}
          </Text>

          <View style={styles.languageContainer}>
            <Text color={'textWhite'}>{language}</Text>
          </View>
        </View>

Los estilos

const styles = StyleSheet.create({
  container: {
    backgroundColor: 'white',
    padding: 5,
  },
  avatarContainer: {
    flexDirection: 'row',
  },
  avatarTextContainer: {
    justifyContent: 'space-between',
    marginLeft: 15,
  },
  languageContainer: {
    backgroundColor: theme.colors.primary,
    padding: 4,
    borderRadius: 2,
  },
  textDescription: {
    flexShrink: 1,
  },
  counterContainer: { justifyContent: 'center', alignItems: 'center' },
  footerItemContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    marginTop: 10,
  },
});

Así luce la vista Captura de Pantalla 2022-08-01 a la(s) 12.44.51.png

El detalle es que el atributo de lenguaje de programación que está de azul debería lucir como un botón y no ocupar toda la fila disponible, aunque se puede ajustar el tamaño del mismo en su sección de estilos llamado "languageContainer" usando width y height otra opción es usar la propiedad "align-self": "flex-start" de modo que ahora lucirá así:

Captura de Pantalla 2022-08-01 a la(s) 12.48.54.png

Ahora observemos otro inconveniente con el texto de la descripción cuando este es muy largo, empiezan a desbordarse de la pantalla, aquí el comportamiento esperando es que pase a la siguiente línea pero luce así:

Captura de Pantalla 2022-08-01 a la(s) 12.51.45.png

Esto lo podemos solucionar desde el contenedor principal del texto "avatarTextContainer" usando la propiedad de estilo "flexShrink": 1 para que el los hijos se logren encoger adecuadamente con lo que hora luce así:

Captura de Pantalla 2022-08-01 a la(s) 12.54.03.png

Código Final

import { Image, StyleSheet, View } from 'react-native';
import React from 'react';
import Text from './Text';
import theme from '../theme';

const RepositoryItem = ({ repository }) => {
  const {
    id,
    fullName,
    description,
    language,
    forksCount,
    stargazersCount,
    ratingAverage,
    reviewCount,
    ownerAvatarUrl,
    url,
  } = repository;

  const counterKsuffix = (amount) => {
    return amount >= 1000
      ? `${Math.round(amount / 100) / 10}k`
      : String(amount);
  };
  return (
    <View style={styles.container}>
      <View style={styles.avatarContainer}>
        <Image style={styles.avatarImg} source={{ uri: ownerAvatarUrl }} />
        <View style={styles.avatarTextContainer}>
          <Text fontWeight={'bold'} fontSize={'subheading'}>
            {fullName}
          </Text>

          <Text
            testID="repositoryDescription"
            style={styles.textDescription}
            color="textSecondary"
          >
            {description}
          </Text>

          <View style={styles.languageContainer}>
            <Text color={'textWhite'}>{language}</Text>
          </View>
        </View>
      </View>
      <View style={styles.footerItemContainer}>
        <View style={styles.counterContainer}>
          <Text fontWeight={'bold'}>{counterKsuffix(forksCount)}</Text>
          <Text>Forks</Text>
        </View>
        <View style={styles.counterContainer}>
          <Text fontWeight={'bold'}>{counterKsuffix(stargazersCount)}</Text>
          <Text>Stars</Text>
        </View>
        <View style={styles.counterContainer}>
          <Text fontWeight={'bold'}>{counterKsuffix(ratingAverage)}</Text>
          <Text>Rating</Text>
        </View>
        <View style={styles.counterContainer}>
          <Text fontWeight={'bold'}>{counterKsuffix(reviewCount)}</Text>
          <Text>Reviews</Text>
        </View>
      </View>
    </View>
  );
};

export default RepositoryItem;

const styles = StyleSheet.create({
  container: {
    backgroundColor: 'white',
    padding: 5,
  },
  avatarContainer: {
    flexDirection: 'row',
  },
  avatarImg: { height: 80, width: 80, borderRadius: 7 },
  avatarTextContainer: {
    justifyContent: 'space-between',
    flexShrink: 1,
    marginLeft: 15,
  },
  languageContainer: {
    alignSelf: 'flex-start',
    backgroundColor: theme.colors.primary,
    padding: 4,
    borderRadius: 2,
  },
  textDescription: {
    flexShrink: 1,
  },
  counterContainer: { justifyContent: 'center', alignItems: 'center' },
  footerItemContainer: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    marginTop: 10,
  },
});