Guía de estilo de React Code | Programar Plus

He estado pasando el mejor momento de mi vida con React últimamente. Pero en mi viaje, tuve dificultades para encontrar buenas pautas de estilo de código para mantener la combinación de JSX y JS limpia y legible. He estado elaborando mis propias guías de estilo que me encantaría compartir. Tal vez estos le sean útiles y, por supuesto, siéntase libre de compartir pautas similares en el hilo de comentarios a continuación.

Regla #1: Desestructura tu props

Una de mis funciones favoritas de ES6 es la desestructuración. Hace que asignar propiedades de objetos a las variables se sienta mucho menos complicado. Echemos un vistazo a un ejemplo.

Digamos que tenemos un perro que queremos mostrar como un div con una clase que lleva el nombre de su raza. Dentro del div hay una oración que anota el color del perro y nos dice si es un perro bueno o malo.

class Dog extends Component {
  render () {
    return <div className={this.props.breed}>My {this.props.color} dog is {this.props.isGoodBoy ? "good" : "bad"}</div>;
  }
}

Eso técnicamente hace todo lo que queremos, pero parece un bloque de código bastante grande para lo que en realidad son solo tres variables y una etiqueta HTML.

Podemos dividirlo asignando todas las propiedades de props a las variables locales.

let breed = this.props.breed;
let color = this.props.color;
let isGoodBoy = this.props.isGoodBoy;

Usando ES6, podemos ponerlo en una declaración limpia como esta:

let { breed, color, isGoodBoy } = this.props;

Para mantener todo limpio, colocamos nuestro operador ternario (más sobre eso más adelante) en su propia variable también, y listo.

class Dog extends Component {
  render () {
    let { breed, color, isGoodBoy } = this.props;
    let identifier = isGoodBoy ? "good" : "bad";
    return <div className={breed}>My {color} dog is {identifier}</div>;
  }
}

Mucho más fácil de leer.

Regla #2: Una etiqueta, una línea

Ahora, todos hemos tenido ese momento en el que queremos tomar nuestra función completa y convertirla en una mezcla de operadores y pequeños nombres de parámetros para crear una función de utilidad fea, súper rápida e ilegible. Sin embargo, cuando está creando un componente sin estado en React, puede hacer lo mismo con bastante facilidad mientras permanece limpio.

class Dog extends Component {
  render () {
    let { breed, color, goodOrBad } = this.props;
    return <div className={breed}>My {color} dog is {goodOrBad}</div>;
  }
}

contra

let Dog = (breed, color, goodOrBad) => <div className={breed}>My {color} dog is {goodOrBad}</div>;

Si todo lo que está haciendo es crear un elemento básico y colocar propiedades en una etiqueta HTML, entonces no se preocupe por darle tanta importancia a todas las funciones y contenedores para obtener una clase completamente separada. Una línea de código servirá.

Incluso puede ser creativo con algunas funciones de distribución de ES6 si pasa un objeto para sus propiedades. Utilizando this.props.content colocará automáticamente la cadena entre la etiqueta de apertura y cierre.

let propertiesList = {
  className: "my-favorite-component",
  id: "myFav",
  content: "Hello world!"
};
let SimpleDiv = props => <div {... props} />;

let jsxVersion = <SimpleDiv props={propertiesList} />;

Cuándo usar la función de propagación:

  • No se requieren operadores ternarios
  • Solo pasar atributos y contenido de etiquetas HTML
  • Se puede usar repetidamente

Cuándo no para usar la función de propagación:

  • Propiedades dinámicas
  • Se requieren propiedades de matriz u objeto
  • Un render que requeriría etiquetas anidadas

Regla #3: La regla de los 3

Si tiene tres o más propiedades, colóquelas en su propia línea tanto en la instancia como en la función de representación.

Estaría bien tener solo una línea de propiedades:

class GalleryImage extends Component {
  render () {
    let { imgSrc, title } = this.props;
    return (
      <figure>
        <img src={imgSrc} alt={title} />
        <figcaption>
          <p>Title: {title}</p>
        </figcaption>
      </figure>
    );
  }
}

Pero considera esto:

class GalleryImage extends Component {
  render () {
    let { imgSrc, title, artist, clas, thumbnail, breakpoint } = this.props;
    return (
      <figure className={clas}>
        <picture>
          <source media={`(min-width: ${breakpoint})`} srcset={imgSrc} />
          <img src={thumbnail} alt={title} />
        </picture>
        <figcaption>
          <p>Title: {title}</p>
          <p>Artist: {artist}</p>
        </figcaption>
      </figure>
    );
  }
}

O el renderizado:

<GalleryImage imgSrc="https://css-tricks.com/react-code-style-guide/./src/img/vangogh2.jpg" title="Starry Night" artist="Van Gogh" clas="portrait" thumbnail="./src/img/thumb/vangogh2.gif" breakpoint={320} />

Puede llegar a ser demasiado bloque de código para leer. Coloque cada propiedad en la siguiente línea para obtener un aspecto limpio y legible:

let { imgSrc,
      title,
      artist,
      clas,
      thumbnail,
      breakpoint } = this.props;

y:

<GalleryImage
  imgSrc="https://css-tricks.com/react-code-style-guide/./src/img/vangogh2.jpg"
  title="Starry Night"
  artist="Van Gogh" 
  clas="landscape"
  thumbnail="./src/img/thumb/vangogh2.gif"
  breakpoint={320} />

Regla #4: ¿Demasiadas propiedades?

La administración de propiedades es complicada en cualquier nivel, pero con la desestructuración de ES6 y el enfoque basado en el estado de React, hay bastantes formas de limpiar el aspecto de muchas propiedades.

Digamos que estamos creando una aplicación de mapas que tiene una lista de direcciones guardadas y una coordenada GPS para su ubicación actual.

La información actual del usuario sobre la posición y la proximidad a la dirección favorita debe estar en el componente principal de la aplicación de esta manera:

class App extends Component {
  constructor (props) {
    super(props);
    this.state = {
      userLat: 0,
      userLon: 0,
      isNearFavoriteAddress: false
    };
  }
}

Entonces, cuando creamos una dirección y queremos que tenga en cuenta qué tan cerca está de la dirección, estamos pasando al menos dos propiedades de la aplicación.

En la aplicación render ():

<Address
  ... // Information about the address
  currentLat={this.state.userLat}
  currentLong={this.state.userLon} />

En la función de representación para el componente de dirección:

render () {
  let { houseNumber,
        streetName,
        streetDirection,
        city,
        state,
        zip,
        lat,
        lon,
        currentLat,
        currentLon } = this.props;
  return ( ... );
}

Ya puedes ver cómo esto se está volviendo difícil de manejar. Si tomamos los dos conjuntos de información y los dividimos en sus propios objetos, se vuelve mucho más manejable.

En nuestra aplicación constructor ():

this.state = {
  userPos: {
    lat: 0,
    lon: 0
  },
  isNearFavoriteAddress: false
};

En algún momento antes de la aplicación render ():

let addressList = [];
addressList.push({
  houseNumber: "1234",
  streetName: "Street Rd",
  streetDirection: "N",
  city: "City",
  state: "ST",
  zip: "12345",
  lat: "019782309834",
  lon: "023845075757"
});

En la aplicación render ():

<Address addressInfo={addressList[0]} userPos={this.state.userPos} />

En la función de representación para el componente de dirección

render () {
  let { addressInfo, userPos } = this.props;
  let { houseNumber,
        streetName,
        streetDirection,
        city,
        state,
        zip,
        lat,
        lon } = addressInfo;
  return ( ... );
}

Mucho, mucho más limpio. React también tiene excelentes maneras de garantizar que las propiedades de los objetos existan y sean de cierto tipo usando PropTypes que normalmente no tenemos en JavaScript, lo cual es una gran cosa OOP de todos modos.

Regla n.º 5: representaciones dinámicas: mapeo de matrices

Muy a menudo en HTML, estamos escribiendo las mismas piezas básicas de código una y otra vez, solo con algunas distinciones clave. Esta es la razón por la que se creó React en primer lugar. Usted crea un objeto con propiedades que devuelven un bloque HTML dinámico y complejo, sin tener que escribir cada parte de él repetidamente.

JavaScript ya tiene una excelente manera de hacer listas de información similar: ¡matrices!

reaccionar utiliza el .map() función para diseñar arreglos en orden, usando un parámetro de los arreglos como key.

render () {
  let pokemon = [ "Pikachu", "Squirtle", "Bulbasaur", "Charizard" ];
  return (
    <ul>
      {pokemon.map(name => <li key={name}>{name}</li>)}
    </ul>
  );
}

Incluso puede usar nuestras prácticas funciones de propagación para arrojar una lista completa de parámetros por un objeto usando Object.keys() (Teniendo en cuenta que todavía necesitamos un key).

render () {
  let pokemon = {
    "Pikachu": {
      type: "Electric",
      level: 10
    },
    "Squirtle": {
      type: "Water",
      level: 10
    },
    "Bulbasaur": {
      type: "Grass",
      level: 10
    },
    "Charizard": {
      type: "Fire",
      level: 10
    }
  };
  return (
    <ul>
      {Object.keys(pokemon).map(name => <Pokemon key={name} {... pokemon[name]} />)}
    </ul>
  );
}

Regla n.º 6: renderizaciones dinámicas: operadores ternarios de reacción

En React, puede usar operadores para hacer una representación condicional como una declaración de variable. En la Regla #1, analizamos esto para indicar si nuestro perro era bueno o malo. No es del todo necesario crear una línea completa de código para decidir una diferencia de una palabra en una oración, pero cuando se trata de grandes bloques de código, es difícil encontrar esos pequeños ?‘arena :‘s.

class SearchResult extends Component {
  render () {
    let { results } = this.props;
    return (
      <section className="search-results">
        {results.length > 0 &&
          results.map(index => <Result key={index} {... results[index] />)
        }
        {results.length === 0 &&
          <div className="no-results">No results</div>
        }
      </section>
    );
  }
}

O, al más puro estilo ternario

class SearchResult extends Component {
  render () {
    let { results } = this.props;
    return (
      <section className="search-results">
        {results.length > 0
          ? results.map(index => <Result key={index} {... results[index] />)
          : <div className="no-results">No results</div>
        }
      </section>
    );
  }
}

Incluso con nuestro ordenado mapeo de resultados, puede ver cómo los corchetes ya se están anidando de manera bastante densa. Ahora, imagine si nuestro renderizado tuviera más de una línea. Puede volverse ilegible con bastante rapidez. Considere una alternativa:

class SearchResult extends Component {
  render () {
    let { results } = this.props;
    let outputJSX;
    if (results.length > 0) {
      outputJSX = (
        <Fragment>
          {results.map(index => <Result key={index} {... results[index] />)}
        </Fragment>
      );
    } else {
      outputJSX = <div className="no-results">No results</div>;
    }
    return <section className="search-results">{outputJSX}</section>;
  }
}

En última instancia, la longitud del código es casi la misma, pero hay una distinción clave: con el primer ejemplo, cambiamos rápidamente de un lado a otro entre dos sintaxis diferentes, lo que dificulta y dificulta el análisis visual, mientras que el segundo es simplemente JavaScript simple con las asignaciones de valor en un idioma coherente y una función de una línea devuelven en otro.

La regla general en esta situación es que si el JavaScript que está poniendo en su objeto JSX tiene más de dos palabras (por ejemplo, object.property), debería estar hecho antes de el return llamar.

Envolver

La combinación de sintaxis puede complicarse, y estas son las situaciones más obvias en las que vi que mi código se descarrilaba. Estos son los conceptos básicos de los que provienen y se pueden aplicar a cualquier situación que no se haya cubierto aquí:

  • Utilice las funciones de ES6. Seriamente. Hay muchas características fantásticas que pueden hacer que su trabajo sea más fácil, más rápido y mucho menos manual.
  • Sólo escriba JSX en el lado derecho de un = o un return.
  • A veces necesitas JavaScript en tu JSX. Si su JavaScript no cabe en una línea (como un .map() función u operador ternario), entonces debe hacerse de antemano.
  • Si su código comienza a verse como (<{`${()}`} />), entonces probablemente haya ido demasiado lejos. Tome el nivel más bajo fuera de la declaración actual y hágalo antes de este.
(Visited 4 times, 1 visits today)