No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Implementando los eventos y transiciones

8/15
Recursos

Aportes 14

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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

Supongo que se esta manejando una nueva versión de xState, ahora para el tema de los send por el momento se deben enviar de esta forma. ```js send({ type: 'START' }); ```send({ type: 'START' });
que ya venga todo por defecto hecho y que no se monte desde 0, o desde un estado muy prematuro del proyecto, me parece un fallo, de un momento a otro, ya teníamos todo el proyecto listo, es muy confuso
Esta genial la forma en que se puede manejar la app con las maquinas de estados, pero no le veo utilidad todo el tiempo, siento que se adecua mas cuando tenemos apps que sean un paso a paso y necesitemos manejar la logica de esta forma.

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.
![](

cómo puedo hacer que el cancel sea un evento global? :think, me gustaría saber como ponerlo en lugar de mandar el mismo método a todos!