3 - Formato JSX

Creamos en el concepto anterior la primer aplicación en React utilizando la aplicación create-react-app y vimos que se genera un archivo llamado App.js y en su interior se crea por defecto la función 'App':

function App() {
  return (
    <h1>Hola mundo</h1>
  );
}

export default App;

Analizaremos ahora cual es el objetivo del valor retornado por la función App.

Problema

Crear el segundo proyecto escribiendo desde la línea de comandos de Node.js:

npx create-react-app proyecto002

La función App no retorna ni HTML, ni Javascript puro, es un nuevo formato propuesto por los creadores de React que luego de ser compilado se genera Javascript puro que lo pueden entender los navegadores.

Hay ciertas reglas que debe cumplir el formato JSX (JavaScript XML), presentaremos algunas de ellas en este segundo ejercicio.

Modifiquemos valor devuelto por la función App:

import './App.css';

function retornarAleatorio() {
  return Math.trunc(Math.random() * 10);
}

function App() {
  const siglo = 21
  const persona = {
    nombre: 'Juan',
    edad: 34
  }
  return (
    <div>
      <h1>Título nivel 1</h1>
      <hr />
      <p>Estamos en el siglo {siglo}</p>
      <h3>Acceso a un objeto</h3>
      <p>{persona.nombre} tiene {persona.edad} años</p>
      <h3>Llamada a un método</h3>
      <p>Un valor aleatorio llamando a un método.</p>
      {retornarAleatorio()}
      <h3>Calculo inmediato de expresiones</h3>
      3 + 3 = {3 + 3}
    </div>
  );
}

export default App;

La función App tiene por objetivo retornar el elemento JSX que representa la interfaz visual de la componente 'App' (por el momento desarrollaremos toda nuestra aplicación en una única componente, luego veremos que un programa se descompone en muchas componentes)

Como vemos dentro del bloque de JSX podemos disponer etiquetas HTML tal como conocemos:

        <h1>Título nivel 1</h1>

Una restricción de JSX es que siempre los elementos HTML deben tener su marca de comienzo y fin, y en el caso que solo tengan una etiqueta que es tanto de comienzo como fin debemos agregar el caracter '/':

        <hr />

Si nos olvidamos de agregar la barra de cierre se genera un error cuando tratamos de compilar la aplicación:

error JSX

Dentro del bloque JSX podemos acceder a variables o constantes indicando entre llaves dicha variable o constante:

        <p>Estamos en el siglo {siglo}</p>

Luego cuando se compila en lugar de la expresión se muestra el contenido de la variable o constante:

expresiones JSX

En forma similar podemos disponer expresiones para acceder a propiedades de un objeto previamente definido:

        <p>{persona.nombre} tiene {persona.edad} años</p>

Otra posibilidad en una expresión es hacer la llamada a otras funciones:

        {retornarAleatorio()}

Podemos inclusive disponer una operación que será ejecutada previo a su visualización:

        3 + 3 = {3 + 3}

Otras restricciones que tiene el formato JSX

Se recomienda dividir el JSX en varias líneas para facilitar la lectura, también recomiendan envolverlo entre paréntesis para evitar los inconvenientes de la inserción automática de punto y coma.

Para definir valores a las propiedades de un elementos HTML mediante expresiones no debemos disponer las comillas. Por ejemplo modifique el método render() y pruebe esto:

import './App.css';

function retornarAleatorio() {
  return Math.trunc(Math.random() * 10);
}

function App() {
  const buscadores = ['http://www.google.com',
    'http://www.bing.com',
    'http://www.yahoo.com'];
  return (
    <div>
      <a href={buscadores[0]}>Google</a><br />
      <a href={buscadores[1]}>Bing</a><br />
      <a href={buscadores[2]}>Yahoo</a><br />
    </div>
  );
}

export default App;

No deben ir las comillas en la asignación de la propiedad href si el valor se extrae de una expresión:

      <a href={buscadores[0]}>Google</a><br />

Si queremos darle el valor directamente si se requieren las comillas:

        <a href="http://www.google.com">Google</a><br />

Podemos plantear funciones que retornen trozos de JSX que luego se agregan al que retorna la función App, probar de modificar nuevamente el problema con:

import './App.css';

function mostrarTitulo(tit) {
  return (<h1>
    {tit}
  </h1>);
}

function App() {
  return (
    <div>
      {mostrarTitulo('Hola Mundo')}
      {mostrarTitulo('Fin')}
    </div>
  );
}

export default App;

Una restricción del JSX es que siempre debe retornar un elemento HTML que puede tener en su interior otros elementos anidados, pero nunca dos elementos HTML hermanos, esto genera un error:

function App() {
  return (
    <div>
      <h1>Titulo 1</h1>
    </div>
    <div>
      <h1>Titulo 2</h1>
  </div>    
  );
}

Debemos disponer obligatoriamente solo un elemento div que envuelva todo:

function App() {
  return (
    <div>
      <div>
        <h1>Titulo 1</h1>
      </div>
      <div>
        <h1>Titulo 2</h1>
      </div>
    </div>
  );
}

Se puede utilizar otros elementos HTML para envolver todo el JSX como por ejemplo 'span', 'section' o cualquier otro, siempre y cuando no haya elementos hermanos en la raíz (inclusive podemos encerrarlo con etiquetas vacías):

function App() {
  return (
    <><div>
      <h1>Titulo 1</h1>
    </div><div>
        <h1>Titulo 2</h1>
      </div>
    </>
  );

Importante

Otra cosa muy importante que hay que tener en cuenta que los nombres de las propiedades de los elementos HTML cambian en varias situaciones:

Debemos utilizar la palabra 'className' en lugar de class (debido a que class es una palabra clave de Javascript):

<h1 className="recuadro">Titulo 1</h1>

Si el nombre de la propiedad está formada por más de una palabra luego el primer caracter a partir de la segunda palabra debe ir en mayúsculas:

<input type="text" tabIndex="1" />