Yo le añadí un botón para ir hacia atrás a partir de passengers.
![](
Introducción a las máquinas de estado
¿Qué son las máquinas de estado en React.js?
Fundamentos de las máquinas de estado
¿Qué es XState?
Creando el bosquejo de nuestra máquina de estado
Machines 101
Declarar la maquina de estados
Estados
Eventos y transiciones
Implementando los eventos y transiciones
Machines 102
Acciones
Contexto
Jerarquías y máquinas paralelas
Servicios
Últimos detalles del proyecto
Cierre
Bonus class: deploy
Clase de cierre
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Estefany Salas
Aportes 14
Preguntas 4
Yo le añadí un botón para ir hacia atrás a partir de passengers.
![](
Si a alguna persona les da error.
// Al enviar el send asi
send('START')
// Haganlo de esta manera
send({ type: "START" });
Si tu tambien sientes como el Profe Juan te mira feo a lo lejos por pasar props de abuelos a nietos, te invito a solucionar este problema con una mejor composición de componentes:
.
Al terminar la clase modifica el archivo BaseLayout y StepsLayout.js
.
src/Containers/BaseLayout.js
import React from 'react';
import { useMachine } from '@xstate/react';
import { StepsLayout } from './StepsLayout';
import { Nav } from '../Components/Nav';
import { Welcome } from '../Components/Welcome';
import { Search } from '../Components/Search';
import { Passengers } from '../Components/Passengers';
import { Tickets } from '../Components/Tickets';
import bookingMachine from '../Machines/bookingMachine';
import './BaseLayout.css';
export const BaseLayout = () => {
const [state, send] = useMachine(bookingMachine);
console.log('state: ', state.value)
return (
<div className='BaseLayout'>
<Nav state={state} send={send} />
<StepsLayout state={state} send={send}>
{state.matches('initial') && <Welcome send={send} />}
{state.matches('search') && <Search send={send} />}
{state.matches('tickets') && <Tickets send={send} />}
{state.matches('passengers') && <Passengers send={send} />}
</StepsLayout>
</div>
);
}
src/Containers/StepsLayout.js
import React from 'react';
import './StepsLayout.css';
export const StepsLayout = (props) => {
return (
<div className='StepsLayout'>
{props.children}
</div>
);
};
Ahora puedes ver como todas las props se comparten desde BaseLayout.js
git clone https://github.com/platzi/react-state-machines.git
git checkout 940935a
npm install
npm run start
.
.
.
src/Containers/BaseLayout.js:
import React from 'react';
import { useMachine } from '@xstate/react';
import { Nav } from '../Components/Nav';
import { StepsLayout } from './StepsLayout';
import bookingMachine from '../Machines/bookingMachine';
import './BaseLayout.css';
export const BaseLayout = () => {
const [state, send] = useMachine(bookingMachine);
console.log('state: ', state.value)
return (
<div className='BaseLayout'>
<Nav state={state} send={send} />
<StepsLayout state={state} send={send} />
</div>
);
}
src/Containers/StepsLayout.js:
import React from 'react';
import { Welcome } from '../Components/Welcome';
import { Search } from '../Components/Search';
import { Passengers } from '../Components/Passengers';
import { Tickets } from '../Components/Tickets';
import './StepsLayout.css';
export const StepsLayout = ({ state, send }) => {
const renderContent = () => {
if (state.matches('initial')) return <Welcome send={send} />
if (state.matches('search')) return <Search send={send} />
if (state.matches('tickets')) return <Tickets send={send} />
if (state.matches('passengers')) return <Passengers send={send} />
return null
};
return (
<div className='StepsLayout'>
{renderContent()}
</div>
);
};
src/Components/Nav.js:
import React from 'react';
import './Nav.css';
export const Nav = ({ state, send }) => {
const goToWelcome = ()=> {
send('CANCEL')
}
return (
<nav className='Nav'>
<h1 className='Nav-logo'>Book a fly ✈</h1>
{!state.matches('initial') &&
<button onClick={goToWelcome} className='Nav-cancel button-secondary'>Cancelar</button>
}
</nav>
);
};
src/Components/Welcome.js:
import React from 'react';
import './Welcome.css';
export const Welcome = ({ send }) => {
const startBooking = () => {
send('START')
}
return (
<div className='Welcome'>
<p className='Welcome-title title'>¡Hoy es el día!</p>
<p className='Welcome-description description'>Compra tu vuelo y conoce un nuevo rincón del mundo, te va a sorprender las maravillas que hay para explorar</p>
<button onClick={startBooking} className='Welcome-cancel button'>Comenzar</button>
</div>
);
};
src/Components/Search.js:
import React, { useState } from 'react';
import './Search.css';
export const Search = ({ send }) => {
const [flight, setFlight] = useState('');
const goToPassengers = ()=> {
send('CONTINUE')
}
const handleSelectChange = (event) => {
setFlight(event.target.value);
};
const options = ['Mexico', 'Venezuela', 'Colombia']
return (
<div className='Search'>
<p className='Search-title title'>Busca tu destino</p>
<select id="country" className='Search-select' value={flight} onChange={handleSelectChange}>
<option value="" disabled defaultValue>Escoge un país</option>
{options.map((option) => <option value={option} key={option}>{option}</option>)}
</select>
<button onClick={goToPassengers} disabled={flight === ''} className='Search-continue button'>Continuar</button>
</div>
);
};
src/Components/Passengers.js:
import React, { useState } from 'react';
import './Passengers.css';
export const Passengers = ({ state, send }) => {
const [value, changeValue] = useState('');
const onChangeInput = (e) => {
changeValue(e.target.value);
}
const goToTicket = ()=> {
send('DONE')
}
const submit = (e) => {
e.preventDefault();
changeValue('');
}
return (
<form onSubmit={submit} className='Passengers'>
<p className='Passengers-title title'>Agrega a las personas que van a volar ✈️</p>
<input
id="name"
name="name"
type="text"
placeholder='Escribe el nombre completo'
required
value={value}
onChange={onChangeInput}
/>
<div className='Passengers-buttons'>
<button
className='Passengers-add button-secondary'
type="submit"
>
Agregar Pasajero
</button>
<button
className='Passenger-pay button'
type="button"
onClick={goToTicket}
>
Ver mi ticket
</button>
</div>
</form>
);
};
src/Components/Tickets.js:
import React from 'react';
import './Tickets.css';
export const Tickets = ({ send }) => {
const finish = () => {
send('FINISH')
};
return (
<div className='Tickets'>
<p className='Tickets-description description'>Gracias por volar con book a fly 💚</p>
<div className='Tickets-ticket'>
<div className='Tickets-country'>Colombia</div>
<div className='Tickets-passengers'>
<span>✈</span>
</div>
</div>
<button onClick={finish} className='Tickets-finalizar button'>Finalizar</button>
</div>
);
};
Comparto el CSS de los botones.
Nav:
.button-secondary{
background-color: white;
border: none;
padding: 8px 14px;
border-radius: 8px;
color: #293684;
}
en App.css :
.button{
background-color: #293684;
border: none;
padding: 8px 14px;
border-radius: 8px;
color: white;
}
Viajando al espacio
Dejo código de la clase con TypeScript + Vite + plugin de xstate en VSC (consultar informacion para generacion de archivo Typegen
Y luego utilizar props en los componentes o containers que lo necesiten:
import { FC } from 'react';
import { Welcome } from '../components/Welcome';
import { Search } from '../components/Search';
import { Passengers } from '../components/Passengers';
import { Tickets } from '../components/Tickets';
import { Props } from '../machines/bookingMachine';
import './StepsLayout.css';
export const StepsLayout: FC<Props> = ({ state, send }) => {
const renderContent = () => {
if (state?.matches('initial')) return <Welcome send={send} />;
if (state?.matches('search')) return <Search send={send} />;
if (state?.matches('passengers')) return <Passengers send={send} />;
if (state?.matches('tickets')) return <Tickets send={send} />;
};
return <div className='StepsLayout'>{renderContent()}</div>;
};
El mío esta quedando así
Interesante, la primera vez que escuche sobre máquinas de estados, lo que pensé fue en que se usa factory para crear estados, pero con esta termine de poder expresarlo.
Normalmente, los estados pueden ser cualquier cosa y tener cualquier cosa, pero las máquinas de estado en realidad es delimitar lo que un estado puede ser o tener.
Como meter agua en una botella.
Mi resultado hasta ahora saudos.
![](
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?