Está en la página 1de 79

REACT

React: Librería creada por Facebook

Kanban: Metodo usado en el desarrollo de software y gestión de procesos.


La metodología Kanban se basa en una filosofía centrada en la mejora continua, donde las
tareas se “extraen” de una lista de acciones pendientes en un flujo de trabajo constante.
La metodología Kanban se implementa por medio de tableros Kanban. Se trata de un
método visual de gestión de proyectos que permite a los equipos visualizar sus flujos de
trabajo y la carga de trabajo. En un tablero Kanban, el trabajo se muestra en un proyecto en
forma de tablero organizado por columnas. Tradicionalmente, cada columna representa una
etapa del trabajo. El tablero Kanban más básico puede presentar columnas como Trabajo
pendiente, En progreso y Terminado. Las tareas individuales —representadas por tarjetas
visuales en el tablero— avanzan a través de las diferentes columnas hasta que estén
finalizadas.

ARQUITECTURA FLUX

Es una arquitectura para el manejo y el flujo de los datos en una aplicación web,
particularmente en el Front-End. Fue ideada por Facebook y vendría a sustituir el patrón
MVC (o MVVM).

El patrón MVC para el Front-End empezó a ser necesario cuando las aplicaciones web
empezaron a hacerse más grandes y con librerías como jQuery o el propio Vanilla
JavaScript se hacían difíciles de manejar. Por eso nacieron frameworks como Backbone,
Ember y/o Angular.
Todos ellos siguen una arquitectura Modelo-Vista-Controlador, o algo parecido (MVVM,
MV*). Haciendo más sencillo el manejo de datos en aplicaciones web con cierto grado de
complejidad.

Flux nació desde Facebook por un problema que se les presentaba al tener una
comunicación bidireccional entre los modelos y los controladores, haciéndoles muy difícil
poder depurar y rastrear errores.

Flux propone una arquitectura en la que el flujo de datos es unidireccional. Los datos
viajan desde la vista por medio de acciones y llegan a un Store desde el cual se actualizará
la vista de nuevo.

Al igual que un patrón MVC está formado por un Modelo, una Vista y un Controlador, en
Flux tenemos distintos actores:
Vista

La vista serían los componentes web, ya sean construidos nativamente, con Polymer, con
Angular, React, etc...

Store

La Store sería lo más parecido al modelo de la aplicación. Guarda los datos/estado de la


aplicación y en Flux puede haber varias (Luego veremos que en algunas implementaciones
sólo hay un único store).

No hay métodos en la Store que permitan modificar los datos en ella, eso se hace a través
de dispatchers y acciones.

Acciones

Un acción es simplemente un objeto JavaScript que indica una intención de realizar


algo y que lleva datos asociados si es necesario. Por ejemplo si tenemos una aplicación tipo
Carrito de la compra, y añadimos un item al carrito, la acción que representaría esto sería:

{
type: 'ADD_ITEM',
item: item
}

Dispatcher

Las acciones como la anterior son enviadas a un dispatcher que se encarga de dispararla o
propagarla hasta la Store.

La vista es la que se encarga de enviar las acciones al dispatcher.

Un dispatcher no es más que un mediador entre la Store o Stores y las acciones. Sirve
para desacoplar la Store de la vista, ya que así no es necesario conocer que Store maneja
una acción concreta.

En Resumen, el patrón FLUX sigue el siguiente recorrido:

 La vista, mediante un evento envía una acción con la intención de realizar un cambio en
el estado
  La acción contiene el tipo y los datos (si los hubiere) y es enviada al dispatcher.
  El dispatcher propaga la acción al Store y se procesa en orden de llegada.
  El Store recibe la acción y dependiendo del tipo recibido, actualiza el estado y
notifica a las vistas de ese cambio.

  La vista recibe la notificación y se actualiza con los cambios.


Todo en un único sentido.

NODE JS

Node.js es un entorno de tiempo de ejecución de JavaScript (de ahí su terminación en .js


haciendo alusión al lenguaje JavaScript). Este entorno de tiempo de ejecución en tiempo
real incluye todo lo que se necesita para ejecutar un programa escrito en JavaScript.
También aporta muchos beneficios y soluciona muchísimos problemas

Node.js fue creado por los desarrolladores originales de JavaScript. Lo transformaron de


algo que solo podía ejecutarse en el navegador en algo que se podría ejecutar en los
ordenadores como si de aplicaciones independientes se tratara

VITE

Vite es una herramienta de compilacion para el Frontend. Lo puedes agrupar en la


categoría donde se encuentran otros como Webpack, Parcel y Snowpack. Es muy útil para
crear una estructura de proyecto que se pueda utilizar con React y de una forma muy
rápida, ya que no necesitas tener que configurar nada.

Como inicializar vite para un proyecto


En la terminal escribir
npm init vite@latest
Darle nombre al proyecto
En el proximo paso seleccionar es React
Seleccionar JavaScript
npm install
npm run dev

Estructura de Archivos de React y Vite

 La carpeta node modules y el archivo package.json, package-


lock.jason surgen de instalar node y npm.
 Si se va a usar un framework css como tailwind o bootstrap, no se
usa el archivo App.css.
 La carpeta public contiene lo ue se va a publicar al alojar el sitio
web
 La carpeta src contiene los archivos del proyecto
 La carpeta assets contiene imágenes y cualquier otro activo del
proyecto
 App.jsx es un componente, es el principal donde se llaman los
demás componentes
 main.jsx es el archivo principal, es el que se encarga de importa
react, de montarlo en el html y de agregar todos los componentes
 ReactDom es la parte de react que se usa en el html
JSX

JavaScript syntax extensión.

Veamos que es JS X es una extensión del lenguaje desarrollada por Facebook (que hoy en
día se conoce como meta )para React

Ahora, como vimos en el video anterior, parece código de JavaScript, pero muestra código
HTML.

Básicamente es un lenguaje de templates que muestra el HTML, pero tiene todas las
funciones de JavaScript.

Todo lo que puedas hacer en JavaScript lo puedes hacer en JS X directamente en el código


HTML.

Una vez compilado, una vez que creas el Bond ,asi se le conoce para publicar tu proyecto
en React,

todos estos pasan a ser archivos JS con funciones y objetos normales, pero cuando estás
desarrollando utilizas JSX.

Con todas estas ventajas de tener el HTML y el JavaScript en un solo lugar, existen ciertas
reglas a la hora de escribir jsx. Los Nombres de los componentes deben comenzar con
mayusculas

A diferencia de HTML que HTML no es para nada estricto, no te puedes crear un DIV y ni
siquiera lo cierras y HTML no te dice nada bueno en jsx, Si una etiqueta HTML tiene
apertura, tienes que agregarle también el cierre.

Lo importante es que, por ejemplo, existen etiquetas de solo apertura, no como, como IMG
o como input. Estos deben de finalizar con diagonal y finalmente el signo de mayor que.

Y muy importante es que también cada componente debe de tener un return.

Y algo importante es que en este return debe haber máximo un solo elemento en el nivel
más alto.

Tus componentes en react se van a dividir en dos partes, lo que está antes del return.
Hay puedes colocar código JavaScript como lo conoces. Funciones XYZ, etc. y lo que
está dentro del return, la segunda es lo que está dentro del return es lo que se va a ver en
pantalla. Los componentes llevan la extension JS y en Vite deben llevar la extension jsx
y se importan con un import de javascritp.

Ahí no puedes colocar funciones y tampoco puedes colocar un IF.


Si se requiere colocar alguna instrucción dentro del return debe ir entre llaves. No se
pueden defini r cosntantes, funciones ni if alli, solo se permite el uso de el operador ternario
y expresiones

Ejemplo

function App() {

cosnt edad=18;

return (

<div className="App">

//{{1+1}

//{edad>=18 ? “Eres mayor de edad” : “No eres mayor de edad”}

<h1>Hola Mundo</h1>

</div>

Considera la declaración de esta variable:

const element = <h1>Hello, world!</h1>;

Esta curiosa sintaxis de etiquetas no es ni un string ni HTML.

Se llama JSX, y es una extensión de la sintaxis de JavaScript. Recomendamos usarlo con


React para describir cómo debería ser la interfaz de usuario. JSX puede recordarte a un
lenguaje de plantillas, pero viene con todo el poder de JavaScript.

const name = 'Josh Perez';


const element = <h1>Hello, {name}</h1>;

function formatName(user) {
return user.firstName + ' ' + user.lastName;
}

const user = {
firstName: 'Harper',
lastName: 'Perez'
};
const element = (
<h1>
Hello, {formatName(user)}! </h1>
);

JSX también es una expresión

Después de compilarse, las expresiones JSX se convierten en llamadas a funciones


JavaScript regulares y se evalúan en objetos JavaScript.

Esto significa que puedes usar JSX dentro de declaraciones if y bucles for, asignarlo a
variables, aceptarlo como argumento, y retornarlo desde dentro de funciones:

function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>; }
return <h1>Hello, Stranger.</h1>;}

Especificando atributos con JSX

Puedes utilizar comillas para especificar strings literales como atributos:

const element = <a href="https://www.reactjs.org"> link </a>;

También puedes usar llaves para insertar una expresión JavaScript en un atributo:

const element = <img src={user.avatarUrl}></img>;

No pongas comillas rodeando llaves cuando insertes una expresión JavaScript en un


atributo. Debes utilizar comillas (para los valores de los strings) o llaves (para las
expresiones), pero no ambas en el mismo atributo.

Advertencia:

Dado que JSX es más cercano a JavaScript que a HTML, React DOM usa la convención de
nomenclatura camelCase en vez de nombres de atributos HTML.

Por ejemplo, class se vuelve className en JSX, y tabindex se vuelve tabIndex.

Especificando hijos con JSX

Si una etiqueta está vacía, puedes cerrarla inmediatamente con />, como en XML:

const element = <img src={user.avatarUrl} />;

Las etiquetas de Javascript pueden contener hijos:


const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);

Estos objetos son llamados “Elementos de React”. Puedes pensar en ellos como
descripciones de lo que quieres ver en pantalla. React lee estos objetos y los usa para
construir el DOM y mantenerlo actualizado.

Reactividad

La reactividad de los datos, simplemente es que la interfaz de usuario de un sitio o


aplicación se modifica a los cambios en los datos de la misma.

Cada vez que se actualizan los datos, la interfaz de usuario lo hace automáticamente para
que coincida con la lógica de programación de la aplicación.

Estado

El estado son los datos de tu aplicación.

Entonces, ¿por qué se le llama estado en lugar de datos?

Porque tiene una duración determinada, el estado son datos en un momento particular de la
aplicación, por ello decimos: el estado actual de los datos de la aplicación.

Interfaz basada en el estado

Una interfaz basada en el estado, es aquella que usa los datos de la aplicación en todo
momento para pintar su elementos visuales.

Los elementos visuales de la interfaz suelen llamarse componentes.

Componentes
Van a permitir dividir tu codigo en partes reutilizables. Los componentes utilizan la
extension .js o .jsx y se importan con un import de JavaScript

Existen varias regls a la hora de escribir componentesen react:


Se colocan dentro una carpeta llamada components ue va dentro de la carpeta src. Se
Escriben con la primera letra en mayuscula y tienen extension .jsx

Se peude pasar informacion de un componente a otro por props

Para definir el término componente citaré la definición de Nicole Sullivan que dice:
“It's a repeating visual pattern, that can be abstracted into an independent snippet of
HTML, CSS and possibly JavaScript.” Nicole Sullivan.

Traduciendo:

Es un patrón visual repetido, que se puede resumir en un fragmento independiente de


HTML, CSS y posiblemente JavaScript.

Los componentes:

 Son un fragmento de la interfaz que cumple una única función.


 Son reutilizables ( principio DRY - Don´t Repeat Yourself ).
 Son independientes, tanto de su contexto como del resto de componentes.
 Son autocontenidos, no filtran estilos o funcionalidad a otros componentes.

Programación Reactiva orientada a Componentes

Con lo descrito anteriormente podemos decir que una aplicación reactiva y basada en
componentes nos permiten separar el código y los elementos de la interfaz en pequeñas
piezas independientes y reutilizables que estarán aisladas una de otras, y en lugar de
intentar apuntar y manipular directamente los elementos del DOM cuando la aplicación
reaccioné a las acciones del usuario, ésta actualizará su estado y luego la interfaz se
repintará con los cambios en el estado.

IMPLEMENTACION DEL CONCEPTODE ESTADO O STATE

Generalmente el state va a ser un objeto donde cada atributo que tenga este objeto va a ser
cada uno de los estados que quisiéramos controlar, recordar que los estados son los datos
que tiene la aplicación en determinado momento.

Componentes y propiedades
Los componentes permiten separar la interfaz de usuario en piezas independientes,
reutilizables y pensar en cada pieza de forma aislada. Esta página proporciona una
introducción a la idea de los componentes

Conceptualmente, los componentes son como las funciones de JavaScript. Aceptan entradas
arbitrarias (llamadas “props”) y retornan elementos de React que describen lo que debe
aparecer en la pantalla.
Componentes funcionales y de clase

La forma más sencilla de definir un componente es escribir una función de JavaScript:

function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}

Esta función es un componente de React válido porque acepta un solo argumento de objeto
“props” (que proviene de propiedades) con datos y devuelve un elemento de React.
Llamamos a dichos componentes “funcionales” porque literalmente son funciones
JavaScript.

También puedes utilizar una clase de ES6 para definir un componente:

class Welcome extends React.Component {


render() {
return <h1>Hello, {this.props.name}</h1>;
}
}

Los dos componentes anteriores son equivalentes desde el punto de vista de React.

Tanto los componentes de función como de clase tienen algunas características adicionales

Renderizando un componente

Anteriormente, sólo encontramos elementos de React que representan las etiquetas del
DOM:

const element = <div />;

Sin embargo, los elementos también pueden representar componentes definidos por el
usuario:

const element = <Welcome name="Sara" />;

Cuando React ve un elemento representando un componente definido por el usuario, pasa


atributos JSX e hijos a este componente como un solo objeto. Llamamos a este objeto
“props”.

Por ejemplo, este código muestra “Hello, Sara” en la página:

function Welcome(props) { return <h1>Hello, {props.name}</h1>;


}

const root = ReactDOM.createRoot(document.getElementById('root'));


const element = <Welcome name="Sara" />;root.render(element);
Recapitulemos lo que sucede en este ejemplo:

1. Llamamos a root.render() con el elemento <Welcome name="Sara" />.


2. React llama al componente Welcome con {name: 'Sara'} como “props”.
3. Nuestro componente Welcome devuelve un elemento <h1>Hello, Sara</h1> como
resultado.
4. React DOM actualiza eficientemente el DOM para que coincida con <h1>Hello,
Sara</h1>.

Nota: Comienza siempre los nombres de componentes con una letra mayúscula.

React trata los componentes que empiezan con letras minúsculas como etiquetas del DOM.
Por ejemplo, <div /> representa una etiqueta div HTML pero <Welcome /> representa un
componente y requiere que Welcome esté definido.

Para saber más sobre el razonamiento detrás de esta convención, puedes consultar JSX en
profundidad.

Composición de componentes

Los componentes pueden referirse a otros componentes en su salida. Esto nos permite
utilizar la misma abstracción de componente para cualquier nivel de detalle. Un botón, un
cuadro de diálogo, un formulario, una pantalla: en aplicaciones de React, todos son
expresados comúnmente como componentes.

Por ejemplo, podemos crear un componente App que renderiza Welcome muchas veces:

function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}

function App() {
return (
<div>
<Welcome name="Sara" /> <Welcome name="Cahal" /> <Welcome
name="Edite" /> </div>
);
}

Por lo general, las aplicaciones de React nuevas tienen un único componente App en lo más
alto. Sin embargo, si se integra React en una aplicación existente, se podría empezar de
abajo hacia arriba con un pequeño componente como Button y poco a poco trabajar el
camino a la cima de la jerarquía de la vista.

Extracción de componentes

No tengas miedo de dividir los componentes en otros más pequeños.

Por ejemplo, considera este componente Comment:


function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}

Acepta author (un objeto), text (un string), y date (una fecha) como props, y describe un
comentario en una web de redes sociales.

Este componente puede ser difícil de cambiar debido a todo el anidamiento, y también es
difícil reutilizar partes individuales de él. Vamos a extraer algunos componentes del mismo.

Primero, vamos a extraer Avatar:

function Avatar(props) {
return (
<img className="Avatar" src={props.user.avatarUrl}
alt={props.user.name} /> );
}

El Avatar no necesita saber que está siendo renderizado dentro de un Comment. Esto es por
lo que le dimos a su propiedad un nombre más genérico: user en vez de author.

Recomendamos nombrar las props desde el punto de vista del componente, en vez de la del
contexto en el que se va a utilizar.

Ahora podemos simplificar Comment un poquito:

function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} /> <div className="UserInfo-
name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}

A continuación, vamos a extraer un componente UserInfo que renderiza un Avatar al lado


del nombre del usuario:

function UserInfo(props) {
return (
<div className="UserInfo"> <Avatar user={props.user} />
<div className="UserInfo-name"> {props.user.name} </div>
</div> );
}

Esto nos permite simplificar Comment aún más:

function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} /> <div className="Comment-
text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
Extraer componentes puede parecer un trabajo pesado al principio, pero tener una paleta de
componentes reutilizables vale la pena en aplicaciones más grandes. Una buena regla en
general, es que si una parte de su interfaz de usuario se usa varias veces (Button, Panel,
Avatar), o es lo suficientemente compleja por sí misma (App, FeedStory, Comment), es
buen candidato para extraerse en un componente independiente.

Las props son de solo lectura

Ya sea que declares un componente como una función o como una clase, este nunca debe
modificar sus props. Considera esta función sum :

function sum(a, b) {
return a + b;
}
Tales funciones son llamadas “puras” porque no tratan de cambiar sus entradas, y siempre
devuelven el mismo resultado para las mismas entradas.

En contraste, esta función es impura porque cambia su propia entrada:

function withdraw(account, amount) {


account.total -= amount;
}

React es bastante flexible pero tiene una sola regla estricta:

Todos los componentes de React deben actuar como funciones puras con respecto a
sus props.

Por supuesto, las interfaces de usuario de las aplicaciones son dinámicas y cambian con el
tiempo. En la siguiente sección, introduciremos un nuevo concepto de “estado”. El estado
le permite a los componentes de React cambiar su salida a lo largo del tiempo en respuesta
a acciones del usuario, respuestas de red y cualquier otra cosa, sin violar esta regla.

CREANDO COMPONENTES

Crear una carpeta llamada components en la carpeta src, dentro crear los componentes que
se requiera con extension jsx. Se pueden crear varios archivos en un componente pero para
mejor legibilidad y organización del codigo se crea un archivo por componente.

La primera letra del nombre del archivo del componente y del componente debe ir en
mayuscula. Cuando se usa vite se usa la extension jsx, si fuese create React App se puede
usar .js o .jsx

EXTENSION ES7 REACT/REDUX/GRAPHQL

Formas de escribir codigo

React Components
rcc
import React, { Component } from 'react'

export default class FileName extends Component {


render() {
return <div>$2</div>
}
}

rce
import React, { Component } from 'react'

export class FileName extends Component {


render() {
return <div>$2</div>
}
}

export default $1

rcep
import React, { Component } from 'react'
import PropTypes from 'prop-types'

export class FileName extends Component {


static propTypes = {}

render() {
return <div>$2</div>
}
}

export default $1

rpc
import React, { PureComponent } from 'react'

export default class FileName extends PureComponent {


render() {
return <div>$2</div>
}
}

rpcp
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'

export default class FileName extends PureComponent {


static propTypes = {}

render() {
return <div>$2</div>
}
}

rpce
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'

export class FileName extends PureComponent {


static propTypes = {}
render() {
return <div>$2</div>
}
}

export default FileName

rccp
import React, { Component } from 'react'
import PropTypes from 'prop-types'

export default class FileName extends Component {


static propTypes = {
$2: $3,
}

render() {
return <div>$4</div>
}
}

rfcp
import React from 'react'
import PropTypes from 'prop-types'

function $1(props) {
return <div>$0</div>
}

$1.propTypes = {}

export default $1

rfc
import React from 'react'

export default function $1() {


return <div>$0</div>
}

rfce
import React from 'react'

function $1() {
return <div>$0</div>
}

export default $1
rafcp
import React from 'react'
import PropTypes from 'prop-types'

const $1 = props => {


return <div>$0</div>
}

$1.propTypes = {}

export default $1

rafc
import React from 'react'

const $1 = () => {
return <div>$0</div>
}

export default $1

rafce
import React from 'react'

const $1 = () => {
return <div>$0</div>
}

export default $1

rmc
import React, { memo } from 'react'

export default memo(function $1() {


return <div>$0</div>
})

rmcp
import React, { memo } from 'react'
import PropTypes from 'prop-types'

const $1 = memo(function $1(props) {


return <div>$0</div>
})

$1.propTypes = {}
export default $1

rcredux
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'

export class FileName extends Component {


static propTypes = {
$2: $3,
}

render() {
return <div>$4</div>
}
}

const mapStateToProps = state => ({})

const mapDispatchToProps = {}

export default connect(


mapStateToProps,
mapDispatchToProps,
)(FileName)

reduxmap
const mapStateToProps = state => ({})

const mapDispatchToProps = {}

ESCRIBIR CSS EN REACT

CSS Plano
Framework CSS
Módulos CSS
Componentes
SASS
Styled Components

TRABAJANDO CON TAILWINDCSS

Comandos:

npm i -D tailwindcss postcss autoprefixer


npx tailwindcss init -p

Esto crea el archivo postcss.config.cjs

En el archivo principal css que este incluido en el main.jsx se coloca lo siguiente

@tailwind base;
@tailwinds components;
@tailwinds utilities

El el archive tailwind.config.js se escibe en el arry content los archivos a los que se les va a
estar agregando el css,es decir que archivos que formaran parte de la presentacion del
proyecto

content: ["./index.html",
"./src/**/*.jsx"]

"./src/**/*.jsx"] Esto indica busca en todas las carpetas de src todos los archivos .jsx donde
quier oque esten disponibles las clases de tailwind

En los archivos jsx las clases se agregan con la palabra className, no se usa class ya que
esta es una palabra reservada de javascript, y aunque jsx no es javascript tiene acceso a
todos los metodos y propiedades del lenguaje

Si se va a trabajar con un archivo propio css se importa en main.jsx de la siguiente forma:


import './index.css'
En este caso el archive contenedor del css se llama index.

HOOKS EN REACT

Los Hooks son funciones que te permiten “enganchar” el estado de React y el ciclo de vida
desde componentes de función. Los hooks no funcionan dentro de las clases — te permiten
usar React sin clases

React proporciona algunos Hooks incorporados como useState. También puedes crear tus
propios Hooks para reutilizar el comportamiento con estado entre diferentes componentes.
Primero veremos los Hooks incorporados.
QUE ES EL STATE?
useState hook para manejar los estados de la aplicacion

El State o estado es basicamente eso; cual es el estado de nuestra aplicación, por ejemplo en
un carrito de conpras el estado se refiere a si el carrito esta vacio o no, que informacion
tiene. En un listado de cliente si se descargo e listado o no, si hubo algun problema, etc.
El Estado es una variable con informacion relevante en nuestra aplicacion de React, algunas
veces el state pertenece a un componente en especifico o algunas veces deseas compartirlo
a lo largo de diferentes componentes.
Al final el state es un destructuring de arreglos

El state es creado con la funcion useState

import {useState} from “react”

const [cliente,setCliente]=useState({})

//cliente: variable que contiene el valor del estado

//setCliente: modificador, funcion que modifica la variable de cliente y solo esa

//useState({}) indica que ese es el valor inicial

Ejemplos de uso de useState y su inicializacion

const[total,setTotal]=useState(0);

const [clientes,setClientes] = useState([]);

const [modal,setModal] =useState(false);

React reacciona en base al state, cada vez que tu state cambia, tu aplicación de React va a
renderizar y actualizarse con esos cambios.

Para modificar el State, se utiliza la funcion que extraemos cuando declaramos el state en
nuestro componente:

La funcion del lado derecho: setCleinte o setTotal , setModal,etc,. Nunca se debe hacer por
asignacion, no se debe asignar el valor de la variable del lado izquierdo por asignacion

IMPLEMENTAR useState

Debe ser declarado en la parte superior del componente, dentro del componente pero antes
del return

Reglas de los Hooks

Los hooks se colocan an la parte superior de tus componentes de React, inmediatamente


despues del nombre de la funcion que contiene el componente.

No se deben colocar dentro de condicionales ni despues de un return


Tampoco se pude colocar si hay un return previo

EVENTOS DE REACT

La forma en la que React maneja los eventos es muy similar a como lo haca JavaScript de
forma nativa, solo con algunos cambios

Los eventos son camelCase. Ejemplo: onChange, onClick

Todos los eventos disponibes en JS estan tambien disponibles en React.


Los eventos se agregan via atributo en el html.

Tambien a diferencia de JS y HTML, donde se coloca el nombre de la funcion en un string


en React(JSX) se utiliza la funcion.

SINTAXIS

HTML JSX
<button onclick=”descargarPedidos()”> <button onclick={descargarPedidos()}>
Descargar Pedidos Descargar Pedidos

</button> </button>

HTML
<form onsubmit=”agregarCliente(): return false”>
<button type=”submit>Submit</button>
</form>

JSX
<form onSubmit{handleSubmit}>
<button type=”submit>Añadir Cliente</button>
</form>

Es importante el orden en que se declaran los state, dee ser en el mismo orden en que se
usan en el documento, por ejemplo conservar el orden de los campos del formulario

PROPS EN REACT

Es una forma de pasar variables o funciones de un componente a otro

Conceptor relacionados con Props o Propiedades

Es State o funciones que creas en tus componentes solo estaran disponibles en ese
componente.
Una forma de evitar duplicar codigo y reutilizar esas variables, state, estado o funciones en
otros componentes es por medio de Props o propiedades.

Los Props se pasan del padre al hijo, nunca se pasan del hijo al padre.

Conceptualmente, los componentes son como las funciones de JavaScript. Aceptan datos de
entrada (llamados props) y returnan elementos de React que describen lo que debería
aparecer en la pantalla.

Las props son la colección de datos que un componente recibe del contenedor padre, y que
pueden usarse para definir los elementos de React que retornará el componente.

En términos prácticos, si un componente necesita recibir información para funcionar, la


recibe vía props.

En términos técnicos, las props tienen ciertas características:

 Son inmutables, que es el adjetivo para lo que no se puede modificar o cambiar.


Una prop no se modifica.
 Pueden tener un valor por defecto
 Pueden marcarse como obligatorias, cuando un componenente no puede funcionar
sin recibir una prop.

En JSX, las props se ven como los atributos de los elementos HTML:

<Btn value=”Enviar” />

Estas props pueden recibir un string o el resultado de una expresión de JavaScript, usando
la sintaxis de llaves:

<Saludo value={` Hola ${nombre} `} />

En componentes funcionales, las props se reciben como argumentos de la función. En


clases se pueden leer vía la propiedad props del objeto:

const Btn = (props)=>{ return null; }

class Btn extends React.Component{


render(){ console.log(this.props); return null; }

SINTAXIS
<Header
nombreProp={datos o funciones}
//LA parte de la izquierda es el nombre del prop, la parte del lado derecho es la variable o
funcion del state o una funcion en caso de haberla creado

/>
Otro Ejemplo
<Header
numeros={1}
clientes={clientes}
isAdmin={false}
setClientes={setClientes}
titulo=”Tienda Virtual”
/>

Si tienes un state que se va a pasar por diferentes componentes, lo mejor es colocarlo en el


archivo principal.

Cada nivel de componentes debera tomar y pasar el Prop hacia otros componentes,
tecnologias como Redux o Context evitan tener que hacerlo de esta forma.

COMO HACER USO DE LOS PROPS ESTABLECIDOS EN EL ARCHIVO


PRINCIPAL

En la parte superiro del archivo App.jsx se coloca import {useState} from ‘react’

Dentro de function App, luego del nombre de la funcion se coloca:


const [arreglo, setArreglo]=useState([])

setArreglo es el modificador del arreglo, ya que las props son inmutables no se pueden
hacer asignaciones o modificaciones sobre ellas directamente sino a traves de setArreglo
donde Arreglo es el nombre de la propiedad, variable, objeto o arreglo.
Se inicializa en vacio.

En la parte superior del componente donde se asignan los props se coloca la palabra
reservada props como parametro de la funcion componente. Si no se quieren pasar todos los
props se aplica destructuring del objeto como parametro y asi se accede a cada prop

function Header(props) {
console.log(props);
return (
<>
<h1 className="font-black text-5xl text-center md:w-2/3 mx-auto">Seguimiento
Pacientes {""}<span className="text-indigo-600">Veterinaria</span></h1>
</>
)
}

export default Header;

Otro Ejemplo
function Header({numeros,isAdmin}) {
console.log(numeros);
console.log(isAdmin);
return (
<>
<h1 className="font-black text-5xl text-center md:w-2/3 mx-auto">Seguimiento
Pacientes {""}<span className="text-indigo-600">Veterinaria</span></h1>
</>
)
}

export default Header;

Ya que los props solo se pasan del padre al hijo y no viceversa, para pasar valores del hijo
al padre se hace lo siguiente:

Se crea en el padre una funcion que debe recibir un(os )parametro(s):

function App() {
const tomaUnValor=(valor)=>{
console.log(valor);
}

return (
<div className="container mx-auto mt-20">
<Header
tomaUnValor={tomaUnValor}

/>
<div className="mt-12 md:flex">
<Formulario

/>
<ListadoPacientes />

</div>

</div>
)
}

export default App

En el archivo del componente Header


function Header({tomaUnValor}) {
tomaUnValor(variableDesdeHeader);
return (
<>
<h1 className="font-black text-5xl text-center md:w-2/3 mx-auto">Seguimiento
Pacientes {""}<span className="text-indigo-600">Veterinaria</span></h1>
</>
)
}

export default Header;

PATRONES PARA PASAR PROPS A OTROS COMPONENTES


props{children}

Children es una palabra reservada en react que hace referencia a todo lo que le pases en un
componente.

Cuando se trabaja con props hay que pasarlos por niveles, desde el padre4 hasta el nivel del
componente donde se necesite.

HELPERS O UTILS

Estos son archivos con funciones utilitarias, se crea una carpeta llamda helpers o utils y
dentro van los archivos con funciones utilitarias y son exension js.
HOOK useEffect

Es el más utilizado luego de useState , siempre es un callback, es decir, va a tener un arrow


function dentrol de el, este se ejecuta cuando el state cambia o cuando el componente esta
listo

Es el sustituto de lo que antes era componentDidMount() y componentDidUpdate()

Usos de useEffect

Este es un Hook y toma un array de dependencias.

Al ejecutarse automaticamente cuando el componente esta listo, es un excelente lugar para


colocar el codigo para coansultar una API o localStorage

También es posible a este useEffect pasarle una dependencia de esa forma va a estar
escuchando por los cambios que sucedan en una variable o en tu state y puede actualizar el
componente cuando ese cambio suceda

Es una funcion que toma un callback como argumento y luego una coma y un arreglo de
dependencias que es el state a escuchar. Si el arreglo de dependencias esta vacio solo se
escucha 1 vez

Sintaxis

import {useeffect} from “react”

useEffect(()=>{
console.log(‘El Componente esta Listo’);

},[uy])

//El arreglo vacio al terminar la arrow function son las dependencias, ese es el valor que va
a estar revisando cuendo cambie, y si cambia realiza un re-render.

Se pueden tener multiples useEffect en el codigo, asi como pueden existrir multiples
usestate. Si las dependencias estan vacias solo se va a ejecutar 1 vez, si las dependencias
tienen un valor se va a ejecutar cada vez que ese valor cambie.

IMÁGENES EN REACT

//Asi se importa
import comida01 from '../images/comida-01.jpg'

//Asi se usa
<img src={comida01} alt=""/>
Ejemplo si se va a buscar una imagen dependiendo de la categoria, es decir se crea un
diccionario de imágenes

const diccionarioIconos = {
ahorro : IconoAhorro,
comida : IconoComida,
casa : IconoCasa,
gastos : IconoGastos,
ocio : IconoOcio,
salud : IconoSalud,
suscripciones : IconoSuscripciones
}

<img src={diccionarioIconos[categoria]} alt="Icono Gasto" />


DEPLOYMENT

Para desplegar un proyecto corremos el comando npm run build . Esto crea una carpeta
llamada buid donde estaran los archivos de produccion del proyecto.

LOGICA DE EDICION USANDO useEffect y el modificador de estado

En el cvomponente formulario se crearon los props y sus respectivos modificadores

const [nombre,setNombre]=useState(' ');


const [propietario,setPropietario]=useState(' ');
const [email,setEmail]=useState(' ');
const [fecha,setFecha]=useState(' ');
const [sintomas,setSintomas]=useState(' ');

En el formulario , los value de los inputs estan atados a estos valores:

<input className="border-2 w-full p-2 mt-2 placeholder-cyan-400


rounded-md" type="text" id="mascota" placeholder="Nombre de la Mascota"
value={nombre}
onChange={(e)=>setNombre(e.target.value)} />

Y se setea o cambia cuando hay un cambio en el value del input, es decir si el usuario teclea
otra cosa, inicialmente el estado de estos props estan como vacio.

useEffect(()=>{
if(Object.keys(paciente).length>0){
setNombre(paciente.nombre);
setPropietario(paciente.propietario);
setEmail(paciente.email);
setFecha(paciente.fecha);
setSintomas(paciente.sintomas);
}

},[paciente])
En este caso useEffect esta siempre monitoreando el objeto paciente, que se diferencia del
arreglo paceintes porque pacientes es un arreglo lleno de una colección de objetos paciente,
este paciente es el que esta en memoria, que cambia o se setea cuando en el componete
paciente se presiona el boton editar:

<button type="button" className="py-2 px-10 bg-indigo-600 hover:bg-indigo-


700 text-white font-bold uppercase rounded "
onClick={()=>{
setPaciente(paciente)
}}>

al darle editar se regresa hacia App.jsx y pasa hacia formulario porque tenemos un props
paciente en formulario , en formulario se extrae en los props que se pasan como argumento
en el componente funcional formulario el useEffect detecta cuando ese cambio surja y eso
es lo que se va a los inputs del formulario por medio del

setNombre(paciente.nombre);
setPropietario(paciente.propietario);
setEmail(paciente.email);
setFecha(paciente.fecha);
setSintomas(paciente.sintomas);
Cambiar el value del boton submit del formulario

Dependiendo de si se esta agregando o editando un paciente se mostrara “Agregar


Paciente” o “Editar Paciente” .

En el value del submit colocar la siguiente funcion de comprobacion en JS

value={paciente.id ?'Editar Paciente' : 'Agregar Paciente'}/>

LOGICA DE DETECTAR UN REGISTRO NUEVO O UNA EDICION

en handleSubmit:
Aquí se realizan las validaciones al presionar submit. El objetoPaciente es el objeto en
memoria de lo que se elee en el formulario, pero a su vez viene un props paciente en
memoria que es el estado paciente que se alamacena al presionar editar paciente.

Se verifica si el objeto props paciente tiene id, de seta asi quiere decir que es una edicion,
en caso contrario es un nuevo registro. objetoPaciente no tiene id, se le genera en caso de
sser un nuevo registro.

Cuando se esta actualizando el paciente si tiene un id, pero objetoPaciente que es el state de
la recoleccion de los datos del formulario no tiene ningun id, en este caso asignamos
objetoPaciente.id=paciente.id

objetoPaciente va a ser el state actualizado y paciente es el state que se genera de presionar


el boton editar, es decir la version anterior.

nos interesa agregar objetoPaciente con setPaciente , para eso se genera un nuevo arreglo
con .map, en donde se itera sobre todos los pacientes(el arreglo de objetos que contiene
todos los pacientes y es el props pacientes) verificando , dentro de este map se verifica si el
id del objeto del state de los datos del formulario es igual al id del pcaiente del state que se
obtuvo al presionar el boton editar es igual, de sera asi retorno el objeto del state de los
datos del formulario que es la actualizacion, en caso contrario retornar el objeto tal cual
como esta que es lo que esta dentro de paciente que es el state que tiene los datos
almacenado.

const pacientesActualizados=pacientes.map(pacienteState=>{
pacienteState.id=paciente.id ?objetoPaciente :pacienteState
})

luego de actualizar el state pacientes hay que limpiarlo, para esto le enviamos desde el
App.jsx el state statePaciente al formulario para extraerlo en el formulario via props y
tenerlo disponible e inicializarlo

NOTAS: En el evento se colocan los state o las funciones de esta forma cuando se requiere
mandar a llamra un parametro:
onClick={()=>setPaciente(paciente)}
No se hace esto:
onClick={sepPaciente()} porque manda a llamar la funcion inmediatamente

tambien se puede hacer lo siguiente :

onClick={handleEliminar} , esto permite que se espere hasta que suceda el evento click

No se coloca onClick={handleEliminar()} ya que esto invoca a la funcion sin importar si


presiono click o no.

LOGICA DE ELIMINAR REGISTRO

Tenemos los pacientes desde el App.jsx y el boton de eliminar esta en el componente


paciente. Se va a crear una funcion en App.jsx que se encargue de tomar el id del paciente
desde el componente paciente y se lo pase a App.jsx por medio de esta funcion.Eso quiere
decir que la funcion eliminarPaciente se le pasa al componente listadoPacientes y luego
como props y de alli se pasa a paciente. Este id se genera cuando al hacer click en agregar
paciente se crea un map donde por cada elemento paciente se crea una entrada en el
componente paciente

Ya de vuelta a App.jsx la funcion eliminarPaciente a traves de filter crea un arreglo donde


filtra todos los registros que no coincidadn con ese id

PROYECTO DE REGISTRO DE GASTOS

Logica de Guardar Gastos

Luego de la validacion de los datos de lgasto se llama una funcion guardar gastos, esta
funcion va aestar en el compomente principal app.jsx, ya que la logica sera pasar los
parametros de esa funcion desde el formualrio donde se recogen. El formulario recolecta
nobre,cantidad y categoria y se envia como un objeto a la funcion guardarGastos en el
comoponente principal, el desarrollo de esta fiuncion lo que hace es tomar ese objeto y
setear el state de gastos creando una copia ue anexe al state de gastos el objeto gasto
recolectado del formulario

VARIOS
leer de un input en teimpo real y guardarlo en prop:
onChange={e=> setValorProp=(e.target.value)}

STYLED COMPONENTS
Styled Components es una de las librerías más populares para inyectar CSS en JavaScript.
No es específica para React ni para ningún otro framework. La puedes utilizar junto con
cualquier framework basado en componentes.
Utiliza template literals u objetos para crear componentes con estilo que puedes usar
directamente en tu código.

Los tratas igual que a los componentes que ya conoces por lo que puedes pasar props, poner
componentes dentro de otros componentes, darle un id, ser reutilizados, entre otras.

Para dar estilo puedes usar CSS y otras funcionalidades adicionales popularizadas por pre-
procesadores como Sass.Styled Components añade una clase única a cada componente para
evitar problemas de especificidad. Además, esto asegura que el buscador solo cargue el
código necesario para cada página de tu aplicación.

Instalación

 Desde el directorio principal de tu aplicación ejecuta el siguiente comando:

npm install -save styled-components


npm install -save styled-components

 En cada archivo en el que lo quieras utilizar, debes importarlo. En la parte superior


del archivo escribe:

import styled from "styled-components";


import styled from "styled-components";

EN ESTE CASO SE VA A USAR 2 DEPENDENCIAS LA PRIMERA ES emotion y se


instala:
npm install @emotion/react @emotion/styled

En el document donde se va a usar styled components se coloca:


import styled from '@emotion/styled'

CUSTOM HOOKS

Una de las razones para crear nuestros propios Hooks es para poder reutilizar una funcion .
Una gran ventaja de crear custom hooks es incorporar el state y todas las funciones de react
y mantener el valor de una funcion de forma persistente

Ventajas de Crear Hooks

Tu codigo personalizado tendra todas las ventajas de React como son: state , effects,
integrar otros hooks y el performance, un hook sera reurilizavle en otros proyectos y en
otros lugares de la pagina

COMO CREAR NUESTROS PROPIOS HOOKS En src se crea una carpeta nueva llamada
hooks, dentro de esta se crean los archivos hooks que queremos crear. Los archivos hooks
por convencion deben inciar su nombre con la palabra use por ejemplo
useSelectMonedas.jsx, la sintaxis puede ser la misma que la que se usa al crear un
componente, con la diferencia de que no tienen el return tradicional de los componentes, un
hook va a retornar ya sea un objeto o un arreglo tal como lo hace el hook de useState

Ejemplo:

const useSelectMonedas = () => {


const SelectMonedas =()=>{
console.log('Desde Select Monedas')
}
return [SelectMonedas] //este return de un arreglo es para que pueda ser usado como hook
}

export default useSelectMonedas

en el archivo donde se va a usar se importa como cualquier componente

Para mandarlo a llamar se extrae (en el componente dond se usa) la funcion del hook, en
este caso SelectMonedas y mandarla a llamar

Al igual que se hace con el useState, se crea


const [SelectMonedas]=useSelectMonedas()
SelectMonedas()

Este es un caso ya usandolo en forma real y practica

const useSelectMonedas = () => {


const SelectMonedas =()=>(
<>
<label>Select Monedas</label>
</>
)

return [SelectMonedas]
}

export default useSelectMonedas

LA funcion SelectMonedas tiene un return de react(noese que la arrow function tiene un


return implicito por los parentesis, y dentro hay un fragment tipico de react

Al hacer la llamada del hook en el componente se puede hacer como si fuese otro
componente mas:

<SelectMonedas /> //y en este caso si va dentro del return del componente
USO DE STATE EN LOS CUSTOM HOOK

const useSelectMonedas = (label,opciones) => {


const [state,setState]=useState('');
const SelectMonedas =()=>(
<>
<Label>{label}</Label>
<Select
value={state}
onChange={e=>setState(e.target.value)}
>
<option value=""

>Selecciona Tu moneda</option>
{opciones.map(opcion=>(
<option
key={opcion.id}
value={opcion.id}
>{opcion.nombre}</option>
))}

</Select>
</>
)

return [state,SelectMonedas]
}

API
API = Application Programming Interface

Funciones, metodos que ofrece una librería para ser utilizada por otro software como una
capa de abstraccion
Una API pone a disposicion recursos que estan alojados en otro servidor o base de Datos

Al ser React una librería que corre en el lado del cliente, no puede consultar una base de
datos, por lo tanto una API es la forma de obtener datos de un servidor

La API puede ser creada en cualquier lenguaje o framework : Python, java, Net
core, Express, Node JS, Laravel, PHP. Para ello deben entregar una respuesta de tipo Json.

Usualmente una API esta creada en JSON

Consultar API con React


Al ser JavaScript puedes utilizar fetch API y obtener los daatos para mostrrlos en pantalla
Algunaas API´s requieren un Key y otras están protegidas por cors
Tambien es posible integrar una librería externa como AXIOS

Librería: Conjunto de funcionalidades empaquetadas que resuleven unas necesidades


especificas del proyecto

Framework: Tiene como principio dar la estructura y el conjunto de funcionalidades para


un proyecto completo desde el inicio hasta el final, en un framework se asegura la
compatibilidad entre todos sus componentes y ademas te da un eaqueleto del proyecto.

CODIGO CONSULTA API

const url=”url”

const consultarAPI=async()=>{
const respuesta=await fetch(url)
const resultado = await respuesta.json();

}
consultarAPI();

ROUTING

Con una librería de Routing se pueden tener diferentes URL´S y mostrar diferentes
componentes, asi como restringir acceso a ciertas páginas.

Un proyecto grande es mejor manejarlo en multiples pantallas, en lugar de 1 solo


componente que revise multiples condiciones .

Librerias de Routing disponibles en React:

La más popular es React Router Dom


Tambien esta Reac Location
Ademas Frameworks y librerias como Next.js, Remix Run, Gatsby, Astro, Hydrogen
cuentan con su propio Sistema de Routing

Ques es REACT ROUTER DOM?

Es una libreria para crear aplicaciones con Routing(diferentes URL´s) . Al tener diferentes
páginas tendremos un mejor orden en nuestro código, y podemos seguir reutilizando
componentes y más

A partir de la versión 6.4 React Router DOM prácticamente se convierte en un framwork


con manejo de rutas, peticiones http, formularios y datos.

COMO INSTALAR REACT ROUTER DOM

npm install react-router-dom


Borrar el app.jsx
Borrar el llamado y la importacion de App en main.jsx

escribir en main.jsx
import {createBrowserRouter, RouterProvider} from ‘react-router-dom

Notas:
createBrowserRouter permite definer un browser por medio de objetos, esto permite
definir todas las rutas por medio de un objeto principal

RouterProvider: Este va a ser el componente principal de la aplicación es como si fuese el


App, sobre el comienzan a fluir los demas componentes de la aplicación, tiene una sintaxis
muy similar a la de un componente:
<RouterProvider />
RouterProvider espera un props que se define con la funcion createBrowserRouter

se crea el router antes del renderizado:

const router=createBrowserRouter([
{
path: ‘/’, //Esto indica que es la página de inicio, puede ser /tienda, etc
element: <h1>Inicio </h1>
}
])

en algunos ejemplos tambien definen una carpeta o un archivo nuevo llamado router,
tambien se puede hacer de esa forma.
createBrowserrouter toma un arreglo en donde se van definir diferentes rutas por medio de
un objeto

path es la forma en la que se van definiendo las diferentes URL´s, e pueden tener un path
para un nosostros, un path para una tienda

element es lo que se va a mostrar en pantalla, puede ser codigo html o un componente

LAYOUT
El layout es el diseño de plantilla que se repite en todas las paginas, es como el patron y
dentro de el va el contenido de los componentes que se renderrizan de forma dinamica, este
renderizado dinamico se logra a traves del componente especial <Outlet /> que es propio de
React Router Dom

Para lograr esto se hace lo siguiente:


Crear euna carpeta llamada components y dentro de ella crear el archivo Layout.jsx

en este archivo se crea el componente con el short code rfce de vite, el cual crea un
componente como una funcion declarada

Este componente se importa en el main.jsx y en el componete router en vez de renderizar el


en el element del objeto una sintaxis html , se renderiza el componente Layout

const router=createBrowserRouter([
{
path:'/',
element:<Layout />
}
])
Para colcoar el contenido dinamico dentro de la plantilla o layout, este se renderiza
definiendo un outlet, se importa como un componente dentro del componente Layout, este
outlet actua como un place holder, como un contenedor dinamico y va a mantener la
apariencia en cada uno de los componentes sin embargo le permite con este outlet que el
contenido que se le pase donde se decida utilizar este layout se va a inyectar a partir de alli,
digamos que se le deja espacio reservado para que en diferentes paginas, diferentes routings
se le diga que se quiere mostrar en esa parte y lo que esta por fuera del Outlet se renderiza
en todos los demas componentes.

Para que funcione, en el codigo se debe hacer lo siguiente:


En el objeto de createBrowserRouter se agrega childre que va a tener un arreglo dentro del
cual va un objeto y todo lo que este dentro de children va a tener aplicado el Layout, va a
heredear el diseño de lo que esta definido en el componente Layout y lo que se le pase
como element se va a inyectar en Outlet

import {Outlet} from 'react-router-dom'

function Layout() {
return (
<div>
<h1>CRM-React-Router-DOM</h1>
<Outlet />
</div>
)
}

export default Layout

E main.jsx

import Layout from './components/Layout'

const router=createBrowserRouter([
{
path:'/',
element:<Layout />,
children: [
{
path:'/nosotros',
element:<h1>Nosotros</h1>
}
]
}

])

Asi como se tiene como element elementos html tambien se puede tener un componente
para que Outlet lo tome

import './index.css'
import Layout from './components/Layout'
import NuevosCliente from './pages/NuevosCliente'

const router=createBrowserRouter([
{
path:'/',
element:<Layout />,
children: [
{
path:'/clientes/nuevo',
element:<NuevosCliente/>
}
]
}

Si se agrega este children


{
index:true,
element:<h1></h1>
},

Se le esta diciendo con index:true que esta es la pagina principal raiz que se muestra, no se
ele incluye path porque no lo requiere ya que con index:true se le dice que es la ruta raiz

Outlet es un componente reservado para que el contenido de os otros componentes que son
hijos que estan definidos en children se inyecten es esa parte.

NAVEGAR ENTRE VARIAS PAGINAS CON REACT ROUTER DOM


Link - NavLink

Al tener una barra de navegacion, en vez de colocar enlces con la etiqueta


<a href=”/”>Clientes </a>
<a href=”/clientes/nuevo”>Clientes </a>

Se usa el componente Link, el cual debe importarse de react-router-dom al igual que Outlet
Para hacerlo de una forma optimizada se usa el componente Link , esta es la sintaxis
<Link to=”/”>Clientes </Link>
<Link to=”/clientes/nuevo”>Clientes </Link>
Al inspeccionar esta pagina en ejecucion, siguen siendo enlaces. Link crea una capa de
abstraccion para hacerlo más optimizado

Existe otro componente que hace practicamente lo mismo y es NavLink, ambos estan
especialmente diseñados para crear barras de navegacion y permitirle al usuario navegar a
lo largo de diferentes páginas
RESALTAR LA PÁGINA ACTUAL
useLocation

Es un hook de react-router-dom . Se importa y se define de la siguiente forma

import {Outlet,Link,useLocation} from 'react-router-dom'

const location=useLocation(); //esta linea se coloca antes del return

location :devuelve un objeto con los siguientes datos

hash: Se refiere al id o ancla que se encuentre en la pagina

pathname: Ubicación en la cual se encuentra el usuario

key: Id unico que se genera de forma dinamica y cambia cada vez que se recarga la página

search: contiene los datos de parametros de busqueda en la url.

Usando el pathname se puede comprar la pagina actual y resaltarla al agregar clases o


acciones en los componentes Link

Ejemplo

<Link className={`${location.pathname ==='/' ? 'text-blue-300 ' :'text-white'}


hover:text-blue-300`} to="/">Clientes</Link>
<Link className={`${location.pathname ==='/clientes/nuevo' ? 'text-
blue-300 ' :'text-white'} hover:text-blue-300`}to="/clientes/nuevo">Nuevo
Cliente</Link>

LOADER

Creando un loader

Usualmente existen paginas donde los datos del contenido que se va a renderizar vienen de
una consulta a una API o una Base de Datos que se guardan en un state, usualmente para
esto se usa un useEffect que vigila que ese componente que el state que contiene esos datos
este listo y de esa forma se carga la informacion.

En la version 6.4 y adelante se usa una funcion llamada loader y no se usa useEffect para
este caso, este loader es una funcion que se crea en el componente donde queremos que se
cargue, en este ejemplo en particular estara en index, desde index se exporta y en main.jsx
se vuelve a iportar usando la declaracion
import Index, {loader as clientesLoader} from './pages/Index'
Loader es una function que se va a ejecutar cuando el componente cargue y es ideal para
cargar un state o para consultar alguna API y obtener algun resultado que se quiera mostrar
en un componente, m este loader siempre debe retornar algo, sino no va a funcionar, puede
retornar una funcion, un arreglo o un string, este retorno usualmente siempre va ser el state
del componente donde esta.

Al importarla se le asigna un alias porque en un proyecto se pueden tener varios loaders


correspondientes a varios componentes y para no chocar con otro se le asigna un alias.

Luego para volverlo a traer al index, para ello en el objeto children del router se coloca
loader: clientesLoader

const router=createBrowserRouter([
{
path:'/',
element:<Layout />,
children: [
{
index:true,
element:<Index/>,
loader: clientesLoader

},
{
path:'/clientes/nuevo',
element:<NuevosCliente/>
}
]
}

])

Y el el componente donde se usa se importa useLoaderDta de react router dom


y se define la variable ue recibe los datos cargados del loader por ejemplo en index:

import{useLoaderData} from 'react-router-dom'


function Index() {
const clientes=useLoaderData();

useNavigate
Es un hook que se usa para navegar de forma programada, es decir,se usa para que en caso
de que elusuario presione en un boton, poder navergar hacia otra página, no en un enlace
sino en un boton, y tambien despues de haber pasado alguna validadción.
Se usa de la siguiente forma

import {useNavigate} from ‘react-router-dom’

antes del return de la function compomnente:

const navigate=useNavigate()

y en el elemento donde se va a usar:

De esta foma nos lleva a la direccion que se le indique como parametro entre los parentesis

<button className="bg-blue-800 text-white px-3 py-1 font-bold uppercase"

onClick={()=>navigate('/') }>Volver</button>

y de esta otra forma nos lleva a la pagina anteior


<button className="bg-blue-800 text-white px-3 py-1 font-bold uppercase"

onClick={()=>navigate(-1) }>Volver</button>
</div>

Existe otra forma de redirecciona r que se llama redirect, epero esre es mejor usarlos en
loaders y en actions.

ENVIAR FORMULARIOS EN React Router DoM

Uso de action

Usualmente en el evento onSubmit de un formulario se asocia una funcion por ejemplo


handleSubmit y dicha funcion se encarga de als acciones a realizar con los datos del
formualrio. Reacr-router-dom tiene ademas de manejo de rutas, manejo de peticiones http,
el envio de un formulario en un peticion http tipo post. El loader se encarga de las
peticiones de tipo get y para las peticiones tipo post tenemos action.

Se realiza a traves de un componente incluido en react router dom llamado Form con F
mayuscula y una funcion que es el action, tien ciertas reglas y debe nombrarse de ciertas
formas

<Form

method=”post”
action>
</Form>

en la parte superior del archivo componente , antes de la funcion componente se define la


funcion action:

export function action(){


//instrucciones a realizar
}

Para hacerle saber al componente Form que tenemos una funcion action que queremos
mandar a llamr una vez se presione el submit se hace lo siguiente:

en el componente main.jsx se importa la funcion action ,


import {action as nuevoClienteAction } from './pages/NuevosCliente'

y en el objeto del children que contiene el formulario se coloca

{
path:'/clientes/nuevo',
element:<NuevosCliente/>,
action:nuevoClienteAction
}

Actions y loaders en React Router 6


Utiliza loaders apra obtener datos de una API o de un objeto (similar a un state)

Utiliza actions para procesar la entrada de datos en un Form

formData

La funcion action que esta asociada a un formulario requiere un request como parametro, es
una peticion que se esta realizando hacia el action. En el protptype del request se encuentr
algo llamado formData, en las peticiones Ajax o fetch se colocan los datos del formulario
en un formData y luego enviarla a un servidor. Es la forma en la que se puede acceder a la
informacion de un formulario.

Esta funcion action debe realizarce de forma asincrona porque el request puede tardar un
rato en procesar y obtener los datos del formData.

Parta obtener los datos del formulario que estan en el formData se debe usar algunos
metodos que estan dentro del formData tales como get o fromEntries

ASI SE USARIA formdata con javascript:

const datos=new FormData();


datos.append('nombre','elsy');
fetch(url,{
body:datos,
method:'POST'
})

Esta es una forma para revisar un dato de formData


const formData=await request.formData();
console.log(formData.get('nombre')) //este nombre es el name del input

Al colocarle un spread operator a un formData si permite leer sus datos, este snippet
permite debugear un formData

const formData=await request.formData();


console.log([...formData])

Una forma aun mejor es esta:

const datos=Object.fromEntries(formData);
console.log(datos)

VALIDACION DE FORMULARIOS EN REACT ROUTER DOM

Primero se debe validar que todos los campos son obligatorios

const errores=[]
if (Object.Values(datos).includes(‘’)){
errores.push(‘Todos los campos deben estar llenos)

//Retornar datos si hay errores


if (Object.keys(errores).length >0{

return errores
}
}

Object.Values(datos) permite acceder a la parte de la derecha de los datos del


objeto,recordar que los objetos estan compuestos por una llave – valor

.includes(‘’) El método includes() determina si una matriz incluye un determinado


elemento, este caso un elemento vacio
const errores=[] es un arreglo de errores que se define vacio, usualemnte no se usa push
cuando se trabaja con state pero como este no es un state no hay ningun problema en
modificar este arreglo.
Estos errores con ese mensaje deben pasar desde el action al comoponente NuevoCliente
que es donde se definio el action porque es donde se necesita , para esto se retorna datos si
hay errores
con esta linea:
if (Object.keys(errores).length >0 esto verifica si el arreglo errores tiene algo

return errores permite que el action retorne los errores. Ahora ya estan listos para pasarse
pero debemos buscar obtenerlos para pasarlos al componente . Al igual que con el loader
existe un hook para usar y se llama useActionDatta.

import {useNavigate,Form, useActionData} from 'react-router-dom'

Se importa en el componente donde se definio el action, asi como el useLoaderData se


importa donde se definio el loader

Y dentro de la funcion componente se inicializa errores como useActionData y asi se puede


leer el contenido del arreglo errores

function NuevosCliente() {
const errores= useActionData();
console.log(errores)

Asi ya aparecen desde el componente y se pueden tomar como datos para mostrar en
cuaquier lugar del componente.

{errores?.length && errores.map((error,i)=><Error


key={i}>{error}</Error>)}

en esta expresion se usa el optional chaining ,permite leer el valor de una propiedad ubicada
dentro de una cadena de objetos conectados sin tener que validar expresamente que cada
referencia en la cadena sea válidaEl operador de encadenamiento opcional proporciona una
forma de simplificar el acceso a los valores a través de objetos conectados cuando es
posible que una referencia o función sea undefined o null.

con esa instruciion se esta diciendo si hay algo en errores porque existe la
propiedad .length, eso quiere decir que hay algo, luego el && es un perador de corto
circuito que indica que si la consicion de la izquierda se cumple entonces se manda a llamar
la de la derecha.

Como puede ser que haya multiples eoorres se le coloca un Key llamado i que es el indice,
la posicion que tendria ese error en el arreglo, ya que este arrglo contendra varios errores de
otros action o vlaidaciones, usualmente no se debe colocar el key con el indice, sobre todo
cuando son datos que pueden cambiar , como por ejemplo clientes ue se pueden eliminar o
agregar mas, aquí no se recomienda hacerlo
useloaderData y useActionData
cuanod usra uno o el otro? esLoaderData se usa cuando se quiera obtener el resultado
dei¡un loadar y useActionData cuendo se queira obtener el resultado de un action , el action
esta vinculado a envios de formualrios.

JSON SERVER – CREACION DE REST API FALSA

Que es una Rest API

REST = Representational State Transfer

Puede ser diseñada en cualquier lenguaje de backend


.

Debe responder a los Request HTTP: GET, POST, PUT, PATCH, DELETE
Tiene una forma ordenana y estructurada de poner a disposicion los recursosos

VERBOS HTTP

GET : Es utilizado para obtener registros de una base de datos o una API
POST: Es usado para Enviar datos al servidor o para creacion de registros
PUT/ PATCH: Es usado para la actualizacion de registros.
DELETE: Es usado para eliminar registros.

ENDPOINTS DE UNS REST API


Una Rest API cuenta con una serie de endpoints o URL’s para realizar las operaciones
CRUD

Obtener o GET de un listado de Todos losClientes:


GET/clientes

Obtener datos de un cliente especifico (id=10)


GET/clientes/10

Creacion de un nuevo Cliente:


POST/CLIENTE

Actualizar o Editar cliente


PUT/clientes/3

Eliminar un cliente
DELETE/clientes/8

CREAR UNA REST API CON JSON SERVER


Getting started

Install JSON Server

npm install -g json-server

Create a db.json file with some data

{
"posts": [
{ "id": 1, "title": "json-server", "author": "typicode" }
],
"comments": [
{ "id": 1, "body": "some comment", "postId": 1 }
],
"profile": { "name": "typicode" }
}

Start JSON Server

json-server --watch db.json

Notaciones importantes de los archivos tipo JSON:


Deben comenzar y terminar con llaves
el objeto que contiene los datos json puede contener un arreglo de objetos:

Ejemplo :

{"clientes" : [
{
" id": 1,
"nombre": "'Juan'",
"telefono": 102013313,
"email": "juan@juan.com",
"empresa": "'Codigo Con Juan'"
},
{
"id": 2,
"nombre": "'Karen'",
"telefono": 138198313,
"email": "karen@juan.com",
" empresa": "'Codigo Con Juan'"
},
{
"id": 3,
"nombre": "'Josue'",
"telefono": 31983913,
"email": "josue@juan.com",
"empresa": "'Codigo Con Juan'"
},
{
"id": 4,
"nombre": "'Miguel'",
"telefono": 319381983,
"email": "miguel@juan.com",
"empresa": "'Codigo Con Juan'"
},
{
"id": 5,
"nombre": "'Pedro'",
"telefono": 1398198938,
"email": "pedro@juan.com",
"empresa": "'Codigo Con Juan'"
}
]
}

CONECTAR EL PROYECTO A JSON SERVER

Crear una carpeta en src llamada data, dentro de esta colocar un archivo, en este caso se
llama clientes.jsx, este archivo va a cntener los datosrealcionados con el cliente y las
consultas CRUD que se hagan .

Se exporta para poder pasar la consulta al componente donde esta la funcion loader , se
defime una funcion async ya que se trabaja con request http y estas pueden tardar en
responder.
como se vaa hacer un fetch se requiere una url, esta se va a guardar en una variable de
entorno, una variable de entorno es una variable que en elentrono de desarrollo puede tener
un valor y en el entrono de produccion tiene un valor diferente.

Cada framework o herramienta que se escoja para crear proyectos tiene una forma de
definir y administrar las variables de entrono. En Vite se hace de la siguiente forma:

Se crea fuera de la crpeta src un archivo llamado .env, dentro de este archivo se escribe lo
siguiente:
VITE_API_URL=http://localhost:3000/clientes

Como se creo un archivo nuevo, se termina la sesion del servidor con ctrl c y se vuelve a
arrancar

Esta variable se puede observar o llamar colocando


import.meta.env.VITE_NOMBRE_VARIABLE, ya sea con un console.log o asignandolo a
una variable para retornarla al componente donde se va a renderizar, estas variables de
entorno siempre hay que crearlas en Vite empezando con VITE_

En el componente donde esta el loader que es donde se usan esots datos , se importa la
funcion obtenerClientes y cuando cargue la funcion loader se manda a llamar.

La funcion obtenerClietnes retorna el resultado de la consulta fetch y el loader retorna el


valor de la funcion obtenerClientes

En /data/clientes

export async function obtenerClientes(){


const respuesta = await fetch(import.meta.env.VITE_API_URL)
const resultado = await respuesta.json()
return resultado

en ./pages/index.jsx

import {obtenerClientes} from '../data/clientes'


export function loader(){
const clientes=obtenerClientes();
return clientes
}

MANEJAR ERRORES

Error Boundaries en React


ocurre cuando carga el componente que estadentro del loader, los error boundaries son un
componente de react que obtiene los errores en cualquier lugar del componente ,ademas
que muestran los errores, muestran cuando ocurren y una interfaz en el componente que
causo los errores, esto es par de react no de react router dom pero ellos hacen uso de el.

En el children se define el errorElement, asi como se define el loader y el action

en main.jsx

import ErrorPage from './components/ErrorPage'

const router=createBrowserRouter([
{
path:'/',
element:<Layout />,
children: [
{
index:true,
element:<Index/>,
loader: clientesLoader,
errorElement:<ErrorPage />

Este Error element puede contener un componente, para esto se crea un componente llamdo
ErrorPage y al igual que el loader requiere un hook que se llama useRouteError que se usa
para pasar el contenido del error al componente y a su vez a la route(el objeto del arreglo
children) que lo contiene

en componente ErrorPage.jsx

import { useRouteError } from 'react-router-dom'

export default function ErrorPage() {


const error = useRouteError()
console.log(error)
return(
<div className='space-y-8'>
<h1 className='text-center text-6xl font-extrabold mt-20 text-blue-
900'>CRM - Clientes</h1>
<p className='text-center'>Hubo un error</p>
<p className='text-center'>{error.statusText || error.message}</p>
</div>
)
}

LOGICA PARA INSERCION DE REGISTROS

NOTAS: react router dom utiliza formdata para almecenar lo que el usuario ha ingresado en
este formulario.
Siguiente paso: como ya se tiene el servicio en la carpeta data, con el archivo clientes, aquí
se genera una funcion encargada de agregarClientes , esta funcion es async porque se usa
fetch API y recibe como parametro los datos que vienen del componente nuevoCliente a
traves del action y el uso del formData.

Siguiente paso abrir el archivo nuevoCliente e importar esa funcion del servicio cliente (en
este caso el servicio cliente es el encargado de manejar las acciones CRUD sobre la API o
Base de Datos) que se acaba de crear.

export async function agregarClientes(datos){


try{
const respuesta = await fetch(import.meta.env.VITE_API_URL,{
method:'POST',
body:JSON.stringify(datos),
headers:{
'Content-Type':'application/json'
}
})
await respuesta.json()
}catch (error){
console.log(error)
}
}

La funcion agregarClientes esta cosntruida de la siguiente forma:

El try catch va a intentar realizar la accion y en case de que se produzca un error ejecuta el
catchy va a mosrtar un mensaje de error parapoderlo debuggear

En el fetch se usa la url guardada een la variable de entorno , este fetch requeiere de otros
parametros ya que el request es POST

method: es el metodo POST


body: son los datos que van a ser agregados a la API o servidor, este es un objeto y como
en la API se insertan datos JSON se deben convertir a JSON con JSON.stringify
headers: es la informacion que se pasa para que sepa que tipo de datos se estan enviando

En el componente nuevoCliente la funcion action es async, ella esta esperando que se


ejecute la funcion delservicio cliente, por eso al hacer la llamada de agregarclientes se
coloca un await porwu se detiene la ejecucion del codigo hasta que se reciban los datos del
procesaiento de esa funcion.

Todo action y loader debe devolver un return, en este caso le retornamos unredirect, en este
caso par el redirect se usa un redirect que viene de react router dom, es por eso que hay que
importarlo junto con los hooks.

Nota importante:

Para redireccionar:

navigate se usa para redireccionar por medio de un boton


link y navlink par redireccionar en barras de navegacion o menus
redirect cuando se vaya a redireccionar al usuario en actions y loaders

EDICION

uso de useParams, router dinamico o url´s dinamicas de react router dom


En main.jsx se crea un nuevo children, esta sera la pagina quese cargara para editar los
datos de un registro, cuando se esta editando un registro se debe tener routing dinamico ya
que se van a tener diferentes clientes y cada uno tien un id y ese id puede ser variable.
React router dom tiene una forma sencilla de manejar esas urlá dinamicas. Se define el
children de la siguiente forma:

en el path usamos una sintaxis especial que inicia con 2 puntos y se le puede asignar a la
variable que sigue a los 2 puntos el nombre que se desee pero es recomendable colocarle un
nombre relacionado con el campo clave que se esta trayendo de la base de datos o API, en
este caso se le coloco clienteId, este nombre de variable es el que react router dom va a
generar en la url

Se crea un componente llamado EditarCliente que va a ser el valor del element, es decitr es
lo que se va a renderizar cuando se cree la url de editar, este componente en este caso se
llama EditarCliente.

Para ir a esa pagina la unica forma de hacerlo es presionando el boton editar del listado de
cliente, para redireccionar con este boton se usa navigate.

El redireccionamiento se hace en el evento onClick del boton y es de la siguiente forma:

import {useNavigate} from 'react-router-dom'


function Clientes({cliente}) {
const navigate=useNavigate

Esto nos va a permitir navegar de forma programada. navigate lleva un parametro, en este
caso la variable que se le va a pasar en un id

<button type="button"
className="text-blue-600 hover:text-blue-700 uppercase font-bold text-xs"
onClick={()=>navigate(`/clientes/${id}/editar`)}>
Editar
</button>

Como obtener el valo rde la url? como bajarlo hacia el codigo?

Se crea un loader en el componente EditarCliente y en este loader se pasa en automatico


algo conocido como params, estos params existen en react router dom , el loader se importa
en el main.jsx y se declara en el children de editar cliente como loader, para ller estos datos
y poder cargarlos en un formaulario y modificarlos debemos hcerlo siguiente:

La logica es Tomar el id del cliente del parametro params que se define en el loader, este id
de cliente es el que agregaremos al resquest GET/clientes/id que se hace mediante la
peticion fetch a la Api, luego de recibir estos datos los mismos se cargan al formulario en
automatico
Paso 1 Obtener los datos asociados al id que viene en la url
Definir una funcion que realice el request de GET mediante fetch a la API
export async function obtenerCliente(id){
const respuesta = await fetch(`import.meta.env.VITE_API_URL/${id}`)
const resultado = await respuesta.json()
return resultado

Importar esa función en el componente editarCliente y hacer uso de ella en el loader para
obtener los datos asociados a ese id de cliente

import {obtenerCliente} from '../data/clientes.js'


export async function loader({params}){
const cliente =await obtenerCliente(params.clienteId)

console.log( cliente)
return cliente
}

Se va a presentar el caso donde se produzca un error al realizar este request a la API o a la


base de datos. Para manejar este error se hace lo siguiente:

En react router dom en el loader se pueden hacer las comporbaciones de datos existentes o
validos.

if(Object.values(cliente)===0){
throw new Response('',{
status:404,
statusText:'Cliente no encontrado'
})
}
el throw new Response() lleva los aprametros status: que define el tipo de error, en este
caso es el 404 por url o pagina no encontrada y el statusText es el texto personalizado que
queremos que vea el usuario.

Ahora al children de editar hay que informarle que hay un error element, eso lo hacemos en
el main.jsx en la descripcion del objeto children

El throw new Response detiene la ejeccuion del cogido y no se retorna el cliente sino la
pagina de error.

Mostrar el registro que se obtuvo con el request GET en el formulario:


Logica
Una vez que el loader hizo la peticion GET a la API, estos datos se guardan en el objeto
cliente que se eobtiene con el loader,estos datos se pasan del loader al main importando el
loader y colocando loader en el children

import EditarCliente, {loader as editarClienteLoader} from


'./pages/EditarCliente'

y de alli se pasan al componente EditarCliente con la importacion y uso de useLoaderData

import {Form,useLoaderData} from 'react-router-dom'


const cliente=useLoaderData()

Se copia el componente Form y el componente Formulario en el comopnente EditarCliente,


al componente Formulario se le pasa el objeto cliente como prop y el llenado automatico se
hace colocando en el value de los input:del omponente formulario
defaultValue={cliente?.nombre}

Para el manejo de errores tambien se pasa al children editarCliente el errorElement.

ACTION PARA ACTUALIZAR REGGISTROS CON PUT

Logica

Para llevar a cabo la accion de actualizar un registro con action es muy parecido a incluir
un nuevo registro, con la diferencia que se debe acceder al id del registro a editar

Primero registrar el action en el componente editarCliente, este action realiza la toma de los
campos del formulario por medio de
const formData=await request.formData();
const datos=Object.fromEntries(formData);

luego realiza unas validaciones de los campos de entrada y luego de pasar las validaciones
se hace llamado a una funcion que debe estar insluida en el servicio clientes.js que esel
archivo que contiene todas las instrucciones de los request de la aplicación, esta funcion es
actualizar cliente, esta funcion va a tomar como parametros request y params , params nos
va a decir que cliente necesitamos actualizar.
En el await se manda a llamar la funcion actualizarCliente que se debio definir en el
servicio clientes.js

Hay que recordar añadir el action en el main.jsx y luego pasarlo al children de editarcliente
en el campo action:

import EditarCliente, {loader as editarClienteLoader, action as editarClienteAction} from


'./pages/EditarCliente'

en el children:

{
path:'/clientes/:clienteId/editar',
element:<EditarCliente />,
loader :editarClienteLoader,
action:editarClienteAction,
errorElement:<ErrorPage />
}

Se define en clientes.js la funcion actualizarCliente que toma 2 parametrso: el id y los datos


del cliente, cuando esta funcion se manda a llamar en el componente editarCliente, el id lo
toma de params.clienteId, este clienteId es el placeholder que se deifnio en la url de editar
del children, y los datos vienen del formData

en clientes.js

en la llamada en el componente:

await actualizarCliente(params.clienteId,datos)

Para leer los errores se coloca :


const errores=useActionData()

Este es un hook que nos permite recuperar la parte del action y useLoaderData nos permite
recuperar la parte del loader

STRAPI CMS Sin Bloques


CONTENT TYPE BUILDER

npx create-strapi-app@latest
Aquí se crean las tablas, cada collection type es una tabla a la que se le pueden agregar
diversos campos

CONTENT MANAGER
Esto es para llenar los datos de las tablas

SINGLE POST TYPE

La diferencia entre un single y un collection es que este solo te permite tener 1 solo
elemento de ese tipo, es decir no se puede crear un colección de datos.

REMIX RUN

Es un framework alternativo a next js para crear sitios y aplicaciones en React que se


ejecuten tanto en el cliente como en el servidor.

Remix es un compilador, un Administrador de peticiones HTTP, un framework par el


servidor y un framework par el cliente.

Es hecho por los creadores de react router dom, se utilizan mucho cosas como actions y
loaders.

Ventajas de Remix
Cero configuracion
Buen performance y esta optimizado para SEO
Routing incluido
Manejo de Peticiones HTTP similar a React router DOM
El codigo sigue siendo React: componentes, hooks, etc

Su sitio es remix.run

Como comenzar a trabajar con Remix Run:

en la terminal escribir el siguiente codigo:

npx create-remix@latest

 Seleccionar just basics


 si no se tiene seleccionado donde se va a hacer el deployment se selecciona Remix
App Server
 Luego de la instalacion ejecutar npm run dev desde la carpeta contenedora del
proyecto (cd nombreCarpetaContenedora)
 Arrastar hasta VS Code

En remix no existe la carpeta src, lo que se renderiza en pantalla viene de la carpeta app.
en la carpeta route esta el archivo index.js que es el que renderiza los componentes. En
remix la carpeta donde se va a escribir la mayor parte del codigo es en la carpeta app, a
diferencia de vite que se hacia en la carpeta src.

El nombre de los archivos es en minusculas. existen 2 archivos importantes:


entry.client.jsx y entry.server.jsx. Una caracteristica importante de remix es que ejecuta
codigo en mabos lados tanto en el cliente como en el servidor. Puede consultar una base de
datos directamente con una ORM como prisma y tambien ejecuta codigo en el cliente.

root.jsx es el archivo principal que ejecuta buena parte de lo que se ve en pantalla.

Al ser un framework que se ejecuta en el servidor se van a encontrar los errores en la


terminal, no es usual ver los errores en la inspeccion de la pagina web, aquí se pueden ver
los errores de la parte que se ejecuta en el cliente

Tiene una carpeta llamada cache para que cada vez que estemso construyendo el sitio no
sea tan lento.

La carpeta build guarda toda la informacion del proyecto, en public hay otra carpeta build
donde se puede guardar imágenes y archivos estaticos

tiene una configuracion eslint, jsconfig.json.

el archivo remix.config.js tiene la configuracion para que remix funcione correctamente

CREANDO APP YDOCUMENT PARA LAYOUT PRINCIPAL

En remix el archivo root.jsx es el archivo principal, es como el main.jsx en vite, ese es el


archivo en el cual s ecomienzan a leer todos los demas componentes y paginas.

Se define dentro este archivo una funcion componente llamada App


export default function App(){
return(
<h1>Hola Desde Remix</h1>
)
}

Algo que tiene remix a diferencia de vite, es que es muy encillo agregar hojas de estilo
para ciertas paginas o modificar todo lo que esta en el head.

para esto se crea un function que se puede llamar Document o Layout y dentro de esta
funcion estara la estructura semantica del html, a esta funcion se le pasa como props
children, de esta forma cuando se incluya en el componente App lo que este como children
se va a renderizar todo lo que se le pase alli:

export default function App(){


return(
export default function App(){
return(
<Document>
<h1>Hola Mundo</h1>
</Document>
)
}

function Document({children}){
return (
<html lang ="es">
<head>
<title>GuitarLA-remix</title>
<body>
{children}
</body>
</head>
</html>
)
}

Lo que esta dentro de las etiquertas de componente <Document> </Document> va a tomar


el lugar de children y se va a renderizar dentro del body

FUNCIONES DE REMIX PARA AGREGAR HOJAS DE ESTILO E


INFORMACIÓN META DENTRO DEL HEAD

Para agregar informacion meta u hojas de estilo se debe exportar una funcion , en el
momento que se exporta va a estar automaticamente disponible en esa ruta

export function meta(){


return (
{
charset:'utf-8',
title:'GuitarLA-Remix',
viewport:"width=device-width,initial-scale=1"
}
)
}

Para poder renderizar estos datos y que se agreguen la meta del componente Document es
necesario importar un componente especial de remix
import {
Meta
} from '@remix-run/react'
export function meta() {
return (
[{
charset: 'utf-8',
title: 'GuitarLA - Remix',
viewport: "width=device-width,initial-scale=1"
}]
)
}

IMPORTANDO HOJAS DE ESTILOS EN REMIX

Se crea una hoja de estilos css, se puede crear una carpeta llamada styles dentro de app y
alli colocar las hojas de estilos. se importa como se importa un archivo de estilos en react,
se crea una funcion export nombrada que se llame links, se importa el componente especial
de remix Links, se coloca el componente links despues del componente meta.

import {
Meta,
Links
} from '@remix-run/react'
import styles from './styles/index.css'

export function links(){


return [
{
rel:styles,
href:styles
}
]
}

function Document({children}){
return (
<html lang ="es">
<head>
<Meta/>
<Links/>
<body>
{children}
</body>
</head>
</html>
)
}
Estas hojas de estilos del componente Links en root se van a cargar en todas las paginas y
em¡n todos los componentes, si se queiren tener hojas de estilos mas pequeñas y mas
particulares se puede exportar esa misma funcion links en diferentes componentes

Ests funcion de meta solo funciona en las paginas definidas en la carpeta routes, no
funciona para los componentes, lo mismo siucede con la funcion links que es para agregar
hojas de estilos y enlacves externos.

AGREGAR FUENTES EXTERNAS Y LINKS EXTERNOS CSS

export function links(){


return [
{
rel: 'stylesheet',
href: 'https://necolas.github.io/normalize.css/8.0.1/normalize.css'
},
{
rel: 'preconnect',
href: 'https://fonts.googleapis.com'
},
{
rel: 'preconnect',
href: 'https://fonts.gstatic.com',
crossOrigin : "true"
},
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?
family=Outfit:wght@400;700;900&display=swap'
},
{
rel:styles,
href:styles
}
]
}

Aquí se agregan fuentes de google font y la hoja de estilos externa de normalize, es


importante el orden ya que el orden en que se coloquen los objetos sera el orden en que
carguen. El crossorigin debe colocarse en true tipo string por requerimientos de remix

OUTLET EN REMIX

Tanto remix como next.js tienen un sistema basado en rutas. Para esto se crea una carpeta
routes dentro de la carpeta app, debe ser asi, porque asi lo requiere remix. Dentro de esta se
crean las rutas o archivos de los cuales se compone nuestra aplicación web. El nombre de
los archivos .jsx debe ser en minuscula porque remix crea automaticamene esa url y las url
son en minuscula. La funcion componente dentro de ese archivo si debe estar escrita en
mayuscula ya que esa es la convencion de React.

En remix para inyectar contenido en otro componente se usa outlet igual que en react
router dom, esto para que el contenido de otro componente se inyecte automaticamente en
el componente App que esta demtro del arcchivo root.jsx

Para esto se importa outlet en el archivo root.jsx junto con meta, links, etc.

El siguiente paso es colocar ese aoutlet dentro del componente Document que esta dentro
de la funcion componente App, ahora ese Componente Outlet seria el children que va
dentro del body que estadentro de Document

export default function App(){


return(
<Document>
<Outlet/>
</Document>
)
}

function Document({children}){
return (
<html lang ="es">
<head>
<Meta/>
<Links/>
<body>
{children}
</body>
</head>
</html>
)
}

Importante recordar que lo que este dentro de la carpeta routes es lo que se va a inyectar en
el outlet del componente app que esta dentro del archivo root.jsx

Si de desea tener una carpeta admin dentro de routes, este admin seria un subdominio y el a
su vez puede tener un index.jsx y la manerade acceder es la siguiente:

nombredominio/admin/index

CREANDO EL HEADER Y ALIAS HACIA LA CARPETA APP


Todo lo que esta en routes son url´s nuevas, pero se puede crear componentes nuevos en
una carpeta llmada componentes dentro de la carpeta app, de esa forma esos componentes
estaran disponibles par ser llamados en cualquier pagina que se quera usar.

Si se quiere crear un header que este presente en todas las paginas se jace lo siguiente:

Crear el componente header en la carpeta components, luego importarlo en root y agregarlo


al coponente Document antes del children, de esta forma:

import Header from './components/header'

function Document({children}){
return (
<html lang ="es">
<head>
<Meta/>
<Links/>
<body>
<Header/>
{children}
</body>
</head>
</html>
)
}

Existe un alias para escribir las rutas de importacion, sualmente se importan las rutas
siguiendo estos enlaces ‘./styles/’ o ‘../components/’, etc, ela alias ~esta definido em el
archivo tsconfig.json en la llave paths
"paths": {
"~/*": ["./app/*"]
}

Esto quiere decir que el carácter ~se refiere a la ruta “./app/*”, es decir todo lo que esta
dentro de app.

AÑADIR CONTENIDO DE NAVEGACION AL HEADER

Para agregar los enlaces se usara el componente <Link to=”/ruta”> </Link>, se importa
Links de @remix-run/react

import {Link} from '@remix-run/react'

function Header() {
return (
<header className="header">
<div className="contenedro barra">
<div className="logo">

</div>
<nav className="navegacion">
<Link to="/"> Inicio</Link>
<Link to="/tienda"> Tienda</Link>
<Link to="/nosotros"> Nosotros</Link>
<Link to="/blog"> Blog</Link>
</nav>
</div>
</header>
)
}

export default Header

MOSTRAR IMAGENES EN REMIX

Importarla como si fuse un componente, la carpeta de las imágenes debe estar en la carpeta
public, esta carpeta tiene el contenido estatico del sitio web.

import logo from '../../public/img/logo.svg'

Y asi se usa en el codigo:

<img className="logo" src={logo} alt="Imagen Logo"/>

RESALTAR LA PAGINA ACTUAL

Se usa el mismo hook que en react-router-DOM, useLocation.


Se importa y se define de la siguiente forma
const location=useLocation(); //esta linea se coloca antes del return

location :devuelve un objeto con los siguientes datos

hash: Se refiere al id o ancla que se encuentre en la pagina

pathname: Ubicación en la cual se encuentra el usuario

key: Id unico que se genera de forma dinamica y cambia cada vez que se recarga la página

search: contiene los datos de parametros de busqueda en la url.


Usando el pathname se puede comprar la pagina actual y resaltarla al agregar clases o
acciones en los componentes Link

CAMBIOS META EN PAGINAS INDIVIDUALMENTE

si se requiere que alguna pagina tenhga informacion meta o codigo css especifica se debe
crear una funcion meta en esa pagina donde se requiere esta informacion personalizada

En el componente nosotrso por ejemplo hacemos lo siguiente:

import styles from '~/styles/nosotros.css'


export function links(){
return [
{
rel:'stylesheet',
href:styles

}
]
}

Esto no elimina las hojas de estilo importadas en root.jsx, solo le añade a nosostros su
propia hoja de estilos.

la funcion meta si sibre escribe la informacion que se coloco en root, ya que por documento
solo puede existir 1 titulo, 1 descripcion, etc.

el atributo rel preload le dice al navegador tan pronto cargues el html, carga determnada
imagen o video porque puede ser muy pesado y debe comenzar a cargar lo antes
posible,esto se coloca en la funcion links

Ejemplo

{
rel:'preload',
href: imagen,
as: 'image'
}

Referencia documentacion preload:


https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/preload.

La ventaja de tener una funcion links dentro de un componente es que si ese componente o
pagina se elimina es mas facileliminar el codigo css vinculado a el.
CONSUMIR EL BACKEND DE STRAPI CON REMIX RUN

Remix Run al igual que react router dom hace uso de loader para obtener informacion de la
API y action para enviar informacion a la api, a diferencia de router dom, con remix no se
necesita enviar el loader al main o en este caso el root ya que al exportarlo directamente en
el archivo componente donde se define se manda a llamar en automatico, no se tiene que
asociar ya que remix run corre en el servidor.

Para consumir esta API de strapi se realiza un fetch desde la funcion loader. Es
conveniente definir la url de la API en una variable de entorno. El archivo .env se crea en la
raiz del proyecto. Se define entonces en .env API_URL= http://127.0.0.1:1337

Y para mandarla a llamar se hace lo siguiente (process.env.nombreVariable esla forma en


que se mandan a llamar las variables de entorno en node)

const respuesta =await fetch(`${process.env.API_URL}/api/guitarras?


populate=image`)
const resultado =await respuesta.json()

OTRA FORMA DE CONSUMIR API USANDO FETCH

Existe otra forma de realizar la consulta en la API y es creando un archivo modelo, como
en el patron MVC, este archivo modelo le dice a remix que la consulta se realiza en el
servidor. Par esto se hace lo siguiente:

Se crea una carpeta llamada preferiblemente models, en la carpeta app. Destro de esta
carpeta se crea un archivo llamado nombreRelacionadoApi.server.js al colocarlo en .server
le estamos diciendo a remix que este archivo solo debe ejecutarse en la parte del servidor,
en ese archivo se coloca la funcion que realiz la consulta fetch y luego esta funcion es
importada y llamada en la pagina donde se deben mostrarlos datos de la consulta.

en el archivo de la carpeta models

export async function getGuitarras(){


const respuesta =await fetch(`${process.env.API_URL}/api/guitarras?
populate=image`)
return await respuesta.json()

En el archivo que muestra los datos de la consulta


import {getGuitarras} from '~/models/guitarras.server'
export async function Loader(){
const guitarras=await getGuitarras()
console.log(guitarras)

return guitarras
}

Consumir una API desde el servidor en lugar de hacerlo directamente desde el cliente tiene
varias ventajas. Aquí te menciono algunas de ellas:

Seguridad: Al consumir una API desde el servidor, puedes mantener tus claves de API y
otros datos sensibles ocultos del cliente. Esto evita que los usuarios finales tengan acceso
directo a información confidencial que podría ser utilizada de manera inapropiada.

Control y autorización: Al tener la lógica de consumo de la API en el servidor, puedes


implementar un control y autorización más estrictos sobre los datos a los que los clientes
pueden acceder. Puedes verificar permisos, autenticar usuarios y aplicar reglas de acceso
antes de permitir que el servidor devuelva los datos solicitados.

Optimización de rendimiento: Al utilizar el servidor como intermediario entre el cliente y la


API, puedes realizar algunas optimizaciones en cuanto al rendimiento. Por ejemplo, puedes
implementar una caché en el servidor para almacenar respuestas de la API y evitar realizar
solicitudes adicionales cuando los datos no han cambiado. También puedes implementar
técnicas de compresión o paginación en el servidor para reducir la cantidad de datos
transferidos al cliente.

Ocultar la complejidad de la API: Si la API que estás consumiendo tiene una estructura
compleja o una interfaz poco amigable, puedes utilizar el servidor para abstraer esa
complejidad y proporcionar una interfaz más simple y fácil de usar para los clientes. El
servidor puede procesar y transformar los datos de la API según sea necesario antes de
enviarlos al cliente.

Evitar problemas de CORS: Al realizar solicitudes desde el servidor en lugar del cliente,
puedes evitar los problemas de política de mismo origen (CORS) que pueden surgir al
hacer solicitudes directas desde el navegador. El servidor actúa como intermediario y puede
realizar solicitudes a otras APIs sin restricciones de CORS.

En resumen, consumir una API desde el servidor en lugar del cliente brinda más control,
seguridad y flexibilidad. Puedes implementar lógica adicional, optimizar el rendimiento y
proporcionar una experiencia de usuario más segura y eficiente. Sin embargo, también
puede agregar complejidad adicional al desarrollo y requerir más recursos de
infraestructura. La elección entre consumir una API desde el servidor o desde el cliente
depende del contexto específico de tu aplicación y tus requisitos.

OBSERVACIONS DE CSS
Cuando se tiene mucho contenido en un parrafo se puede colocar la siguiente sintaxis css
para mover el contenido hacia arriba.
.guitarra .descripcion{
display:-webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
overflow: hidden;
}

ROUTING DINAMICO CON REMIX RUN

En el ejemplo de las guitarras en el listado de la tienda guitarras se coloco un link con la


siguiente ruta:

<Link className="enlace" to={`/guitarras/${url}`}>Ver Producto</Link>

Alli se puede ver que apunta auna ruta /guitarras y lo que viene despues /${url}es el
atributo url unico de ruta para acceder a cada guitarra.

Para lograr esto en remix run , se crea en la carpeta routes un archivo con la siguiente
sintaxis de anidamiento:
guitarras.$guitarraUrl.jsx Este caso especifico guitarras es el Api ID en plural que me da
strapi y guitarra es el Api en singular, url se refiere al atributo url de cada guitarra
para que lea el atributo dinamicamente o la url con el nombre de la guitarra, se debe crear
un archivo con una sintaxis de nombre especial:

Debe iniciar con signo de $ ,despues se coloca el nombre que se quiere y es .jsx, tenendo en
cuenta que la forma en que se nombre ese archivo va a ser la forma en que se recupera el
parametro desde la url al hacer el loader y la consulta api.

No importa como se nombre la funcion componente, siempre y cuando tenga /guitarras y


despues algo, este va a ser el componente que se va a renderizar en pantalla.porque el signo
$ al inicio lo hace un componente o una ruta dinamica.

Lo ideal es que si hago click en determinada guitarra en ver producto, se traiga la


informacion de la API relacionada con esa guitarra, para esto vamos a hacer uso del loader
en el componente routing Guitarra que esta en el archivo guitarras.$guitarraUrl.jsx

FILTRAR LAS GUITARRAS POR EL ATRIBUTO URL

En este loader se va a tener como parametro un request y tambien un param


export async function loader({params}){
const {guitarraUrl}=params
//console.log(params)
const guitarra=await getGuitarra(guitarraUrl)
//console.log(guitarra)
return guitarra
}

en params nos trae guitarraUrl que es como se nombro ese parametro, con esta informacion
podemos hacer la consulta para traernos esa guitarra en especifico de la API, es vital saber
que al hacer el loader de todas las guitarras este params trae toda la data de la API y se
renderiza un componete guitarra por cada elemento del arreglo, esto se hace con el .map

function Tienda() {
const guitarras = useLoaderData()

return (

<main className="contenedor">
<h2 className="heading">Nuestra Colección</h2>
{guitarras?.length &&(
<div className="guitarras-grid">
{ guitarras.map(guitarra=>(
<Guitarra
guitarra={guitarra?.attributes}
key={guitarra?.id} />
))}
</div>

)}
</main>
)
}

export default Tienda

Cuando se creo el contenido de la API se creo un atributo url, que es unico y es amigable
para SEO, para formar la url de la consulta fetch se coloca de la siguiente forma:

localhost:1337/api/guitarras?filters[url]=valorurl&populate=imagen

El signo de interrogacion eso es a lo que se le llama "URL Query string". El ?"" se utiliza
para dividir el URL del Query string. El Query string es básicamente una lista de variables
y sus valores
el & es para decirle que busque ese otro atributo, es un ‘Y’ esto tambien
esta url se usa en la consulta fetch getGuitarra que estara en el archivo de modelos
guitarras.server.js

export async function getGuitarra(url){

const respuesta = await fetch(`${process.env.API_URL}/api/guitarras?


filters[url]=${url}&populate=imagen`)
return await respuesta.json()
}

AÑADIR LOS DATOS META DEL HTML DINAMICAMENTE

En el componente guitarrs.$guitarraUrl tambien se puede exportar la funcion meta. Una vez


que el loader tiene informacion y la pasa al componente tambien se pasa data.

export function meta({data}){


console.log(data)

return [ ]
}

Este console.log nos da como resultado:


data: [ { id: 5, attributes: [Object] } ],
meta: { pagination: { page: 1, pageSize: 25, pageCount: 1, total: 1 } }

Este data es de los params de remix, esto es un arreglo que en la posicion 0 tiene un objeto
que es el data de los datos de strapi

para acceder a los de strapi hacemos lo siguiente:


console.log(data.data[0])

{
id: 5,
attributes: {
nombre: 'Townshend',
createdAt: '2023-05-29T21:18:56.226Z',
updatedAt: '2023-05-29T21:19:03.885Z',
descripcion: 'Sed convallis dui elementum, ultricies urna vitae, consequat lacus. Duis a
tristique mi, ac auctor lorem. Curabitur eu erat tempor, aliquet metus pharetra, efficitur
augue. Fusce consectetur sapien ut varius lacinia. Etiam mollis commodo purus id fringilla',
precio: 489,
url: 'townshend',
publishedAt: '2023-05-29T21:18:56.226Z',
imagen: { data: [Object] }
}
}
y nos da este objeto, para acceder a los datos de la guitarra

{
id: 5,
attributes: {
nombre: 'Townshend',
createdAt: '2023-05-29T21:18:56.226Z',
updatedAt: '2023-05-29T21:19:03.885Z',
descripcion: 'Sed convallis dui elementum, ultricies urna vitae, consequat lacus. Duis a
tristique mi, ac auctor lorem. Curabitur eu erat tempor, aliquet metus pharetra, efficitur
augue. Fusce consectetur sapien ut varius lacinia. Etiam mollis commodo purus id fringilla',
precio: 489,
url: 'townshend',
publishedAt: '2023-05-29T21:18:56.226Z',
imagen: { data: [Object] }
}
}

entonces para acceder a los atributos hacemos lo siguiente

console.log(data.data[0].attributes.nombre)

y esto se coloca en la funcion exportada meta:

export function meta(){


return[
{title:'GitarLA - Tienda de Guitarras',
description:'GuitarLA - Nuestra Coleccion de Guitarras'}
]
}

MOSTRAR UN MENSAJE DE ERROR SI UNA ENTRADA O PAGINA NO FUE


ENCONTRADA

Cuando se hace la consulta en la aPI trae el objeto Data, si no existe algo ese objeto data
viene vacion y eso produce un error en remix ya que remix intenta leer los attributes..

el manejo de errores en remix se hace a traves del uso del hook useCatch y de los
componentes CatchBaoundary y ErrorBoundary

En el archivo root se importa el hook useCatch y se definen esa 2 funcnionen componentes

Según la documentacion de remix run en root.jsx se importa:


import {isRouteErrorResponse, useRouteError} from '@remix-run/react'

y se escribe el siguiente componente:


/***********Manejo de Errores *************/

export function ErrorBoundary(){


const error = useRouteError()

if (isRouteErrorResponse(error)) {
return (
<Document>
<p className="error">
{error.status} {error.statusText}
</p>
</Document>

);
}
}

Esto lo que hace es que cuando existe un error en la ruta componente , el componente
ErrorBoundary sera renderizado en su lugar, anidado dentro de cualesquiera rutas padres.
Los componentes ErrorBoundary ademas se renderizan cuando hay un error en las
funciones loader o action de una ruta, de forma tal que todos los errores para esa ruta
puedan ser manejados en un solo sitio.

CONSULTANDO LOS POSTS EN STRAPI

Al igual que con las guitarras, debemos crear una funcion en el modelo para hacer el fetch
de la API, en este caso se crea unarchivo llamado posts.server.jsx, alli se crea una funcion
exportada para hacer la consulta fetch.

export default async function getPosts() {


const respuesta =await fetch(`${process.env.API_URL}/api/posts/?
populate="imagen`)
return await respuesta.jason

En la ruta Blog se crea la funcion loader que llama a la funcion getPosts del modelo para
renderizar lo que viene de la API de strapi, de aquí viene post.attributes que es quein
contiene la informacion del post

el loader del blog:

export async function loader(){


const posts=await getPosts()

return posts.data
}

El componente haciendo el llmado a renderizar el componente post por cada elemento post
del arreglo posts que viene de la API (se usa .map())

function Blog() {
const posts =useLoaderData()

//console.log(posts)
return (
<main clasName="contenedor">
<h2 className="heading">Blog</h2>
<div className="blog">
{posts.map(post=>(
<Post
key={post.id}
post={post}

/>
))}
</div>
</main>
)
}

export default Blog

en el componente Post del archivo llamado post,jsx de la carpeta components

import {Link} from '@remix-run/react'

export default function Post({post}) {


const {contenido, imagen, titulo, url, publishedAt } = post.attributes
console.log(post)
return (
<article className="post">

<div>
<img src={imagen.data.attributes.formats.small.url} alt={titulo}/>
<div className="contenido">
<h3>{titulo}</h3>
<p classNAme="fecha">{publishedAt}</p>
<p className="resumen">{contenido}</p>
<Link className="enlace" to ={`/posts/${url}`}>Leer Post</Link>
</div>

</div>

</article>
)
}

NOTA IMPORTANTE CSS CORTAR PARRAFOS

.post .resumen{
display:-webkit-box;
-webkit-box-orient:vertical;
-webkit-line-clamp: 4;
overflow: hidden;
}

AGREGAR UTILIDADES EN REMIX RUN

Se crea una carpeta llmada utils, dentro de ella se crea un archivo helpers.js, la extension en
.js porque no se mezclara codigo js con html.

Formatear fecha:

Se crea una funcion que recibe la fecha que viene como dato del blog de la consulta a la
API , se convierte a un objeto fecha para usar el metodo .toLocaleDateString().

El método toLocaleTimeString() devuelve una cadena con una representación de la parte


del tiempo de esta fecha sensible al idioma. Los nuevos argumentos locales y options le
permiten a la aplicación especificar el idioma cuyas convenciones de formato deben usarse
y personalizan el comportamiento de esta función. En implementaciones antiguas que
ignoran los argumentos locales y options la localidad usada y la forma de la cadena
devuelta son completamente dependientes de la implementación.

export const formatearFecha=fecha=>{


const fechaNueva =new Date(fecha)
const opciones={
year:'numeric',
month: 'long',
day:'2-digit'
}

return fechaNueva.toLocaleDateString('es-ES',opciones)
}
export default {
formatearFecha
}

MULTIPLES LLAMADAS A API EN UN COMPONENTE

Se puede hacer multiples llamada a la PI en un mismo componetne usando una funcion


loader. Para esto se usa Promise.all. Esto porque en elsta proyecto especifico las guitarras y
los posts no esan relacionados, es decir no se debe esperar con await a que cargue una
consulta para entonces llamar a la otra, sino que se pueden traer las 2 consultas de una vez

export async function loader(){


const [guitarras,posts]=await Promise.all([getGuitarras(),getPosts()])
return {
guitarras:guitarras.data,
posts:posts.data
}
}

y al hacer el llamado del loader

const {guitarras,posts}=useLoaderData()

El archivo index debe nombrarse _index.jsx.

Luego de tener el objeto resultado de la consulta fetch en la API se extraen esos datos para
pasarlos a los componentes correspondientes y se rendericen.

Ejemplo
en la funcion componente Index
{guitarras?.length &&(
<div className=”contenedor-guitarras”>
{guitarras.map((meal => (
<Guitarra
key={guitarra?.id}
guitarra={guitarra?.attributes}
/>
)))

</div>)}
{posts?.length &&(
<div className=”contenedor-posts”>
{posts.map((post)=>(
<Post
key={post?.id}
post={post?.attributes}
/>
))}
</div>

)}

Cuando necesitamos colocar imagenes como background image y no podemos importar un


archivo de jsx(por ejemplo la imagen que hemos obtenido del fetch a la API de Strapi)
dentro de una hoja de estilos css, lo que se hace es inyectar los estilos por jsx dentro del
componente
Ejemplo:

<style jsx="true">{`
.curso {
background-image: linear-gradient( to right, rgb(0 0 0 / .65),
rgb(0 0 0 / .7) ), url(${imagen.data.attributes.url})
}
`}</style>

NESTED ROUTING EN REMIX

Nested Routes:
La idea general de la asignación de rutas a segmentos de la URL permite que la URL
completa se asigne a una jerarquía de componentes de ruta y dependencias de datos que se
pueden conocer antes de la representación.

Remix usa el archivo root.jsx ubicado en el directorio app como el archivo de entrada base
para renderizar cada ruta; se puede pensar en el archivo root.jsx como el contendor global
de tu aplicación, el cual usa Remix para cargar o renderizar las rutas correspomndientes.

Sin embargo un componente outlet es requerido dentro del archivo root.jsx par que Remix
sea capaz de averiguar que ruta cargar

El Componente Outlet y Como funciona

El componente outlet es la clave para el Nested Routing en Remix. Este habilita a un


componente a anidar y renderizar un child matched dentro del el. Por ejemplo, es usado
para decirle a una ruta o componente padre donde dejar o poner una ruta hija anidada

export default function App() {


return (
<html>
<head>{/* title, meta info, etc. */}</head>
<body>
<h2>Global App Container</h2>
<Outlet />
</body>
</html>
);
}

Ahora que hemos colocado el componente outlet dentro de este componente, este sera
responsable de descubrir que ruta cargar en este componente, dependiendo de la url
visitada. Si visitamos una url que encaje con una ruta, este componente outlet lo descifrara
y cargara alli la ruta correspondiente.

Retornaemos un simple “Hello World” desde routes/index.jsx y tratamos de visitar esa ruta,
la cual es el homepage (/) de nuestra aplicación

export default function Index() {


return <h1>Hello World</h1>;
}

El resultado sEria:

Global App Container

Hello World

como es esperado, nuestro archivo global root.jsx fue renderiado al DOM y, a traves del
uso del componente outlet, la correspondiente ruta visitada fue montada (anidada) dentro de
el.

Lo mismo pasaria con cualquier ruta visitada: El archivo root.jsx actua como base
contenedora de las rutas mientras que el componente outlet descifra que ruta debe ser
cargada dependiendo de la url visitada

COMO FUNCIONA EL ENRUTAMIENTO DINAMICO EN REMIX

Una de las caracteristicas mas poderosas incorporadas Remix es su mecanismo de


enrutamiento anidado; puede usar el componente outlet para construir una jerarquia de rutas
anidadas para formar lo que podria ser mejor descrito como una plantilla o layout anidado.
En el ejemplo anterior se uso un pequeño enrutamiento anidado,cuando anidamos el
archivo index.jsx dentro del archivo componente root.jsx, pero esto es solo rasgar la
superficie de sus capacidades.

Imagina por un momento que estamos construyendo un dashboard de ventas de algun tipo,
y en nuestro directorio de rutas creamos un archivo dashboard.jsx.

routes
┣ dashboard.jsx

┗ index.jsx

Por defecto, si visitamos la ruta /dashboard , Remix renderizaria este archivo. Ahora,
imagina que hemos creado un nuevo directorio con el mismo nombre que nuestro archivo
dasboard y, en este nuevo archivo de directorio, creamos otro archivo llamado sales.jsx

routes

┣ dashboard

┃ ┗ sales.jsx

┣ dashboard.jsx

┗ index.jsx

Remix automaticamente asociaria esta nueva carpeta de ruta /dashboard al archivo de ruta
dashboard.jsx e intenta anidar cada ruta ubicada dentro de esta carpeta /dashboard dentro
del layout dashboard.jsx

Lineamientos remix para nested routing

https://remix.run/docs/en/1.15.0/file-conventions/route-files-v2#nested-routes

AGREAGAR AL CARRRITO CON LOCAL STORAGE

Crear el formulario en el componente donde se reuqiera

<form className="formulario">
<label htmlFor="cantidad">Cantidad</label>

<select id="cantidad"
onChange={e=>setCantidad(+ e.target.value)}

>
<option value="">--Selecccione--</option>
<option value="1" >1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
<input
type="submit"
value="Agregar al carrito"
/>

</form>

Crear el state para guardar en este caso la cantidad ya que al colocar el formulario en el
componente de la guitarra seleccionada tenemos acceso a sus datos que vienen del loader.

Se debe importar el hook useState en la cabecera del componente

import { useState } from 'react'

Se define el hook en su lugar correspondiente; luego de la definicion de la funcion


componente y antes del return

function Guitarra() {
const [cantidad,setCantidad] =useState(0);

Se asigna el valor de cantidad cuando cambie el option del select, con el evento onChange

<select id="cantidad"
onChange={e=>setCantidad(+ e.target.value)}

>

Este carrito de compras va a enviar los datos a la


API local storage que se ejecuta en el lado del cliente. si se enviara a un servidor se le
colocaria method=”post” en el formulario, pero en este caso se usara el evento submit para
manejar el almacenamient ode los datos del carrito en la API local storage

<form onSubmit={handleSubmit} className="formulario">

CONTEXT API

Mantener Estado Global sin dependencias, permite evitar tener que pasar el estado desde el
componente a otro a traves de props.

Puedes pasar el state o funciones desde un componente principal hasta los hijos, sin
necesidad de pasarlo por cada componente. Tiene su propio Hook llamado useContext.
Remix y Next JS tienen un context integrado, por eso cuando con ellos no e usa
useContext.

Tambien se puede pasar o actualizar el state desde el componente hijo (o ejecutar una
funcion que lo actualice)

Se puede tener un archivo con el estado global y todas las funciones que modifican el state
y pasarlo o actualizar el estado ya sea con un click o cuando se descargue una lista de
clientes, etc.

Si deseas crear librerias para react, Context es la forma de hacerlo. Basicamente context va
a ser un componente y una vez que se importe se tiene acceso a las funciones en cualquier
lugar de la aplicación. Es muy parecido a los hooks useLoaderData, esta inspirado en esto.

Desventaja: Muchos re-renders (es pintar la interfaz varias veces)

También podría gustarte