TSX

  • TSX és una extensió sintàctica per Typescript que et permet escriure codi que s'assembla a HTML dins d'un fitxer Typescript

    Introducció

    TSX s’assembla molt a l’HTML, però és més estricte i pot mostrar informació dinàmica.

    Et permet tenir en el mateix lloc el contingut i la lògica de renderització.

    Entorn de treball

    Instal·la Deno.

    Crea un projecte amb el nom tsx, especificant directament el nom del projecte i la plantilla que vols utilitzar:

    deno init --npm vite tsx --template react-swc-ts

    Instal·la les dependències:

    
    cd tsx
    deno install --allow-scritps

    Instal·la tailwindcss i @tailwindcss/vite

    deno install --allow-scripts npm:tailwindcss npm:@tailwindcss/vite

    Afegeix el complement @tailwindcss/vite a la teva configuració de Vite.

    import { defineConfig } from 'vite'
    import react from '@vitejs/plugin-react-swc'
    import tailwindcss from '@tailwindcss/vite'
    
    // https://vite.dev/config/
    export default defineConfig({
      plugins: [react(),tailwindcss()],
    })

    Modifica el contingut del fitxer src/index.css

    @import "tailwindcss";

    Arrenca el servidor de desenvolupament:

    deno run dev

    Obre el navegador: http://localhost:5173

    Veuras la pàgina d’inici per defecte:

    Elimina el fitxer src/App.css.

    Modifica el fitxer src/App.tsx:

    export default function App() {
      return <h1>Hello</h1>
    }

    El prefix export default és part de la sintaxis estàndard de Typescript (no és específic de React).

    Et permet marcar la funció principal d’un arxiu perquè després la puguis importar en altres arxius.

    Regles

    A continuació veurem les regles TSX.

    Només pots retornar un únic element arrel

    export default function App() {
      return (
        <h1>Alí Bey</h1>
        <p>Aquesta és la història</p>
      )
    }

    Si has de retornar més d’un element, els has d’afegir tots dins d’un element arrel.

    Per exemple, pots utilitzar un <div>:

    export default function App() {
      return (
        <div>
          <h1>Alí Bey</h1>
          <p>Aquesta és la història ...</p>
        </div>
      )
    }

    Una altra opció és utilitzar l’element buit <>:

    export default function App() {
      return (
        <>
          <h1>Alí Bey</h1>
          <p>Aquesta és la història ...</p>
        </>
      )
    }

    Aquest element és invisible i no genera cap element de marcatge.

    export default function App() {
      return (
        <>
          <h1>Alí Bey</h1>
          <p>Aquesta és la història ...</p>
        </>
      )
    }

    Tanca tots els tags

    Totes les “etiquetes” TSX s’ahn de tancar de manera explícita.

    En aquest exemple tens una etiquet <img> que no està tancada:

    export default function App() {
      return (
        <img src="https://upload.wikimedia.org/wikipedia/commons/4/48/Rough_Collie_600.jpg">
      )
    }

    L’has de tancar de manera explícita:

    export default function App() {
      return (
        <img src="https://upload.wikimedia.org/wikipedia/commons/4/48/Rough_Collie_600.jpg"/>
      )
    }

    camelCase

    TSX es converteix en Typescript, i els atributs dels elements TSX es converteixen en atributs d’objectes TypeScript.

    Per exemple, <img src="rough-collie"/> es converteix en l’objecte:

    const image = { src: "rough-collie" }

    Per tant, els noms dels atributs TSX estan limitats pels noms que poden tenir els atributs d’objecte Typescript.

    Per exemple, els noms no poden tenir guions o utilitzar paraules reservades com class.

    export default function App() {
      return (
        <div class="container">
          <img src="https://upload.wikimedia.org/wikipedia/commons/4/48/Rough_Collie_600.jpg"/>
        </div>
      )
    }

    Com que class és una paraula reservada, has d’utilitzar className, el nom de la propietat que correspon al DOM:

    export default function App() {
      return (
        <div className="container">
          <img src="https://upload.wikimedia.org/wikipedia/commons/4/48/Rough_Collie_600.jpg"/>
        </div>
      )
    }

    Pots trobar tots aquests atributs a la llista de propietats de component del DOM.

    Typescript dins de TSX

    Amb la clau {} pots afegir referenciar una propietat dinàmica dins del “markup”:

    export default function App() {
    
      const radius = 5
      const area = 3.141592653 * (radius ** 2)
    
      return (
        <div className="container m-5">
          <p>Area of {radius} is {area}</p>
        </div>
      )
    }

    També pots afegir codi Typescript directament codi:

    export default function App() {
    
      return (
        <div className="container m-5">
          <p>Area of 9 is {3.141592653 * (9 ** 2)}</p>
        </div>
      )
    }

    Això també inclou el cridar funcions:

    export default function App() {
    
      function area(radius: number) {
        return 3.141592653 * (radius ** 2)
      }
    
      return (
        <div className="container m-5">
          <p>Area of 5 is {area(5)}</p>
        </div>
      )
    }

    Debugger

    Pots utilitzar la instrucció debugger per analitzar el codi en execució.

    Per exemple:

    export default function App() {
    
      const radius = 7
    
      debugger
    
      const PI = 3.141592653
    
      const area = PI * (radius ** 2)
    
      return (
        <div className="container m-5">
          <p>Area of 5 is {area}</p>
        </div>
      )
    }
    • Obre la pàgina amb el navegador “Google Chrome”: http://localhost:5173
    • Obre l’eina per desenvolupadors del navegador amb Ctrl+Shift+I.
    • Refresca la pàgina F5

    //tsx/debugger.gif

    Renderitzat condicional

    Pots utilitzar la sentència if per controlar quin arbre TSX es tornarà en funció d’una condició:

    export default function App() {
    
      const age = 17
    
      if (age < 18) {
        return (
          <div className="container m-5">
            <p className="text-warning">Encara ets massa jove per entrar al club de les tortugues</p>
          </div>
        )
      }
    
      return (
        <div className="container m-5">
          <p>Benvigut al club 🐢🐢🐢 !</p>
        </div>
      )
    }

    En aquest exemple pots veure que una part del contingut està duplicat.

    Si vols pots utilitzar l’operador ? : dins una clau {} per eliminar codi duplicat:

    export default function App() {
    
      const age = 17
    
      return (
        <div className="container m-5 text-center">
          <p className="fs-1 m-2">🐢</p>
          { age < 18 ?
            <p className="text-warning">Encara ets massa jove per entrar al club de les tortugues</p> :
            <p>Benvigut al club 🐢🐢🐢 !</p>
          }
        </div>
      )
    }

    També pots utilitzar l’operador && per generar contingut només si es dona una condició:

    export default function App() {
    
      const age = 120
    
      return (
        <div className="container m-5 text-center">
          <p className="fs-1 m-2">🐢</p>
          { age < 18 ?
            <p className="text-warning">Encara ets massa jove per entrar al club de les tortugues</p> :
            <p>Benvigut al club 🐢🐢🐢 !</p>
          }
          { (age > 100) && <p className="fs-5 m-t 3">🌈 Ets una super tortuga!</p>}
        </div>
      )
    }

    Si vols pots guardar codi TSX en una variable:

    // TODO

    Llistes

    Una situació habitual és que tinguis una llista, i vols mostrar tots (o alguns) elements de la llista.

    Amb el mètode map() pots transformar la llista en una llista d’elements TSX.

    export default function App() {
    
      const people = [
        'Creola Katherine Johnson: mathematician',
        'Mario José Molina-Pasquel Henríquez: chemist',
        'Mohammad Abdus Salam: physicist',
        'Percy Lavon Julian: chemist',
        'Subrahmanyan Chandrasekhar: astrophysicist'
      ]
    
      return (
        <div className="container m-5">
          <ul>
            {people.map(person => <li>{person}</li>)}
          </ul>
        </div>
      )
    }

    Si només vols mostrar aquelles persones que són químics, pots utilitzar el mètode filter() per filtrar la llista:

    export default function App() {
    
     // ...
    
      const chemists = people.filter(person => person.includes("chemist"))
    
      return (
        <div className="container m-5">
          <ul>
            {chemists.map(chemist => <li>{chemist}</li>)}
          </ul>
        </div>
      )
    }

    Activitat

    1. A continuació tens una llista de temperatures mitjes mensuals de l’aire de la ciutat de Barcelona des de l’any 2000.

    export default function App() {
    
      const tss = [
        [2000, 7.7, 11.4, 12.6, 13.3, 18.3, 21, 22.8, 24.5, 21, 16, 11.3, 11],
        [2001, 9.9, 10.1, 14.8, 13.8, 18.2, 21.9, 23.7, 25, 19.6, 19.4, 10.7, 6.8],
        [2002, 9.2, 11.1, 12.3, 13.7, 15.5, 22.3, 22.9, 21.6, 19.9, 17.4, 13, 10.4],
        [2003, 7.9, 7.1, 12.1, 14, 18, 25.6, 26.1, 28.5, 20.8, 15.2, 12.7, 8.8],
        [2004, 9.4, 8.6, 10, 12.8, 16.2, 22.4, 23.5, 25.1, 21.4, 18.9, 11.4, 9.3],
        [2005, 7.2, 6.5, 10.2, 14, 18.8, 23.4, 24.4, 23, 20.7, 17.9, 11.1, 6.6],
        [2006, 7.4, 8.5, 12, 15.1, 18.7, 22.1, 27.1, 22.8, 21.6, 18.8, 14.6, 10],
        [2007, 9.9, 11.4, 12.1, 15, 17.9, 22, 23.6, 22.5, 20.6, 16.4, 11.2, 8.8],
        [2008, 10.1, 10.2, 10.8, 13.7, 16.6, 20.7, 23.8, 24.3, 20.7, 16.5, 10.3, 7.5],
        [2009, 7.2, 8.7, 11.2, 13.1, 18.8, 23, 24.4, 26.3, 21.5, 17.9, 13.5, 9],
        [2010, 6.6, 8, 9.6, 14.1, 15.4, 20.3, 25.7, 24.3, 20.9, 16.2, 11, 8.5],
        [2011, 8.4, 10, 10.9, 15.9, 18.3, 19.5, 21.2, 24.1, 22.9, 19.1, 14.1, 10.2],
        [2012, 9.4, 6.8, 13.4, 12.6, 17.9, 22.3, 23.2, 26, 21.4, 17.3, 12.7, 9.9],
        [2013, 9.1, 7.7, 11.2, 13.5, 14.6, 19.5, 25.6, 24.9, 22.0, 19.5, 12.2, 10.1],
        [2014, 9.8, 10.1, 12.3, 15.3, 16.2, 21.7, 22.6, 23, 22, 19.6, 13.6, 9.1],
        [2015, 9.1, 8.2, 12, 14.8, 19.1, 23.2, 26.0, 23.50, 19.7, 16.7, 14.3, 12.6],
        [2016, 10.7, 11.3, 11.1, 13.6, 16.4, 21.6, 24.9, 24.5, 22.3, 17.1, 12.7, 11.5],
        [2017, 7.9, 11.4, 13.3, 14.2, 18.3, 23.6, 24.2, 24.5, 19.5, 18.6, 12.5, 8.5],
        [2018, 10.5, 6.7, 10.8, 14.7, 17.1, 21.5, 25.3, 25.8, 22.5, 17.0, 12.4, 11.1],
        [2019, 8.1, 11.9, 13.5, 13.4, 15.6, 21.9, 25.4, 25.1, 21.8, 18.5, 11.9, 11.2],
        [2020, 10.0, 12.8, 11.9, 14.3, 19.4, 20.1, 25.0, 25.5, 21.7, 16.4, 14.7, 9.3],
        [2021, 7.7, 11.6, 12.1, 12.9, 17.3, 23.3, 24.8, 24.5, 23.0, 18.1, 11.3, 10.9],
        [2022, 10.2, 11.8, 10.8, 14.1, 20.7, 24.7, 26.7, 27.2, 22.5, 20.7, 15.2, 12.6],
        [2023, 9.2, 10.3, 14.1, 16.1, 18.1, 23.4, 25.5, 26, 23.2, 20.2, 14.8, 12.1]
      ]
    
      return <h1>Temperatures Barcelona</h1>
    }

    Has de mostrar la informació en una taula:

    Temperatures de Barcelona
    Any Gener Febrer Març Abril Maig Juny Juliol Agost Setembre Octubre Novembre Desembre
    2000 7.7 11.4 12.6 13.3 18.3 21 22.8 24.5 21 16 11.3 11
    2001 9.9 10.1 14.8 13.8 18.2 21.9 23.7 25 19.6 19.4 10.7 6.8
    2002 9.2 11.1 12.3 13.7 15.5 22.3 22.9 21.6 19.9 17.4 13 10.4
    2003 7.9 7.1 12.1 14 18 25.6 26.1 28.5 20.8 15.2 12.7 8.8
    2004 9.4 8.6 10 12.8 16.2 22.4 23.5 25.1 21.4 18.9 11.4 9.3
    2005 7.2 6.5 10.2 14 18.8 23.4 24.4 23 20.7 17.9 11.1 6.6
    2006 7.4 8.5 12 15.1 18.7 22.1 27.1 22.8 21.6 18.8 14.6 10
    2007 9.9 11.4 12.1 15 17.9 22 23.6 22.5 20.6 16.4 11.2 8.8
    2008 10.1 10.2 10.8 13.7 16.6 20.7 23.8 24.3 20.7 16.5 10.3 7.5
    2009 7.2 8.7 11.2 13.1 18.8 23 24.4 26.3 21.5 17.9 13.5 9
    2010 6.6 8 9.6 14.1 15.4 20.3 25.7 24.3 20.9 16.2 11 8.5
    2011 8.4 10 10.9 15.9 18.3 19.5 21.2 24.1 22.9 19.1 14.1 10.2
    2012 9.4 6.8 13.4 12.6 17.9 22.3 23.2 26 21.4 17.3 12.7 9.9
    2013 9.1 7.7 11.2 13.5 14.6 19.5 25.6 24.9 22 19.5 12.2 10.1
    2014 9.8 10.1 12.3 15.3 16.2 21.7 22.6 23 22 19.6 13.6 9.1
    2015 9.1 8.2 12 14.8 19.1 23.2 26 23.5 19.7 16.7 14.3 12.6
    2016 10.7 11.3 11.1 13.6 16.4 21.6 24.9 24.5 22.3 17.1 12.7 11.5
    2017 7.9 11.4 13.3 14.2 18.3 23.6 24.2 24.5 19.5 18.6 12.5 8.5
    2018 10.5 6.7 10.8 14.7 17.1 21.5 25.3 25.8 22.5 17 12.4 11.1
    2019 8.1 11.9 13.5 13.4 15.6 21.9 25.4 25.1 21.8 18.5 11.9 11.2
    2020 10 12.8 11.9 14.3 19.4 20.1 25 25.5 21.7 16.4 14.7 9.3
    2021 7.7 11.6 12.1 12.9 17.3 23.3 24.8 24.5 23 18.1 11.3 10.9
    2022 10.2 11.8 10.8 14.1 20.7 24.7 26.7 27.2 22.5 20.7 15.2 12.6
    2023 9.2 10.3 14.1 16.1 18.1 23.4 25.5 26 23.2 20.2 14.8 12.1

    2. A continuació has de posar color a les celes.

    Mostra en:

    1. Color blau les temperatures inferiors a 10
    2. En color vermell les temperatures superiors a 20
    Temperatures de Barcelona
    Any Gener Febrer Març Abril Maig Juny Juliol Agost Setembre Octubre Novembre Desembre
    2000 7.711.412.613.318.32122.824.5211611.311
    2001 9.910.114.813.818.221.923.72519.619.410.76.8
    2002 9.211.112.313.715.522.322.921.619.917.41310.4
    2003 7.97.112.1141825.626.128.520.815.212.78.8
    2004 9.48.61012.816.222.423.525.121.418.911.49.3
    2005 7.26.510.21418.823.424.42320.717.911.16.6
    2006 7.48.51215.118.722.127.122.821.618.814.610
    2007 9.911.412.11517.92223.622.520.616.411.28.8
    2008 10.110.210.813.716.620.723.824.320.716.510.37.5
    2009 7.28.711.213.118.82324.426.321.517.913.59
    2010 6.689.614.115.420.325.724.320.916.2118.5
    2011 8.41010.915.918.319.521.224.122.919.114.110.2
    2012 9.46.813.412.617.922.323.22621.417.312.79.9
    2013 9.17.711.213.514.619.525.624.92219.512.210.1
    2014 9.810.112.315.316.221.722.6232219.613.69.1
    2015 9.18.21214.819.123.22623.519.716.714.312.6
    2016 10.711.311.113.616.421.624.924.522.317.112.711.5
    2017 7.911.413.314.218.323.624.224.519.518.612.58.5
    2018 10.56.710.814.717.121.525.325.822.51712.411.1
    2019 8.111.913.513.415.621.925.425.121.818.511.911.2
    2020 1012.811.914.319.420.12525.521.716.414.79.3
    2021 7.711.612.112.917.323.324.824.52318.111.310.9
    2022 10.211.810.814.120.724.726.727.222.520.715.212.6
    2023 9.210.314.116.118.123.425.52623.220.214.812.1