So I've been stuck on this assignment for about a week now on this one part. I've asked a question about it here but due to my inexperience with React I still can't figure out how to solve it. The assignment is as follows:
The goal of this project is to create an application that simulates the operation of a cafe. You will need to create components for the customer, barista, and coffee machine.
Customer component
This is the "User facing" component. Here you should have 3 option items that will cause this component to fire a custom event. These options are: Drip brew, french press, and espresso.
When one of the objects is clicked, it should highlight and stay highlighted until another is clicked.
Barista Component
This component takes the orders, and displays a response on the DOM, formatted as such:
"One {{ order_type }}? That will be {{ order_value }}."
When taking a new order, play an animation to transition out the next text, and transition in new text.
After a delay of five seconds (use the setTimeout method), fire an event to start the preparation of the coffee. Change the text in this component to read, "Waiting for {{ order_type}}"
This component also needs a method that will be called when the machine finishes it preparation. This "coffeeFinished" method should display a message like so: "Here is you {{ order_type }}, enjoy!".
When taking a new order, play an animation to transition out the next text, and transition in new text.
Machine Component
This component, when its "brewCoffee" method is called, should display a message visually to the user that says "Currently brewing: {{ order_type }}".
Again, using setTimeout, have this component wait five seconds before firing a "brewingComplete" event. When this event is fired, also change this component's output to "{{ order_type }} is done."
While the coffee is brewing, a loading bar needs to be animated to display how much time until the process is over.
The Application Object
The application object will be responsible for listening for each of the events fired from your components, and calling the appropriate methods on the next in line. For instance, when the Machine Component fires the event "brewingComplete", the application should respond to the event by calling the deliver order method on the Barista component.
Additionally, this component should store the current order name in its properties. This is the variable that should be referenced when displaying the order being brewed and repeated by the barista.
The problem I've been having is taking one component, in this case when a user pushes a button, and using those values in the other components with the timeout function. What I have so far is:
App.js
import React, { Component } from 'react';
import './App.css';
import './Customer.js';
import Customer from './Customer.js';
import './Barista.js';
import Barista from './Barista.js';
import './CoffeeMachine.js';
import CoffeeMachine from './CoffeeMachine.js';
class App extends Component {
//The State with all the stuff that gets updated along the way
state = {
coffee: "",
value: 0,
bgColor: 'transparent'
}
//I apparently can't comment in the render thing without it appearing on the page. So, the Green box for the Customer Component, the Orange box for the Barista Component, and the Blue Box for the Machine component.
render() {
return (
<div className="App">
<div className="row" id="green">
<Customer order = {(coffeeSelect, value) => {this.send(coffeeSelect, value)}}/>
</div>
<div className="row" id="orange">
<Barista coffeeSelect = { this.state.coffee } value = { this.state.value }/>
</div>
<div className="row" id="blue">
<CoffeeMachine coffeeSelect = { this.state.coffee } value = { this.state.value }/>
</div>
</div>
)
}
//Sends the selected values to the other components
send(coffeeSelect, value) {
this.setState({coffee: coffeeSelect, value: value});
}
}
export default App;
Customer.js
import React, { Component } from 'react';
import './Customer.css';
class Customer extends Component {
//Each button has a div to be highlighted upon being selected
render() {
return(
<div>
<div className="button">
<button onClick={() => { this.optionSelect("Drip")}}>
Drip
</button>
</div>
<div className="button">
<button onClick={() => { this.optionSelect("French Press")}}>
French Press
</button>
</div>
<div className="button">
<button onClick={() => { this.optionSelect("Espresso")}}>
Espresso
</button>
</div>
</div>);
}
//Receives the brew, and assigns it to its matching cost
optionSelect(userChoice) {
var coffeeSelect = userChoice;
var value = 0;
if (coffeeSelect === "Drip"){
value = 5;
} else if (coffeeSelect === "French Press"){
value = 6;
} else if (coffeeSelect === "Espresso"){
value = 3;
}
this.props.order(coffeeSelect, value);
console.log(coffeeSelect);
console.log(value);
}
}
export default Customer;
Barista.js
import React, { Component } from 'react';
class Barista extends Component {
//The default text in the Barista Component until the user sends it the coffee and cost
state = {
text: "Hello, How May I Help You Today?",
orderText: "One " + this.props.coffee + "? That will be $" + this.props.value
}
//This is where I've hit the brick wall. I just need to get the buttons to also call this thing but everything I've looked up just gives me errors. If I could figure out where to call this I can do the timer to "prep" the coffee.
confirm(){
this.setState({ text: "One " + this.props.coffee + "? That will be $" + this.props.value});
setTimeout(() => {this.waiting()}, 5000);
}
waiting() {
this.setState({ text:"Waiting for " + this.props.coffee});
setTimeout(() => {this.finish()}, 5000);
}
finish() {
this.setState({ text: "Here is your " + this.props.coffee + ". Enjoy!"});
}
render() {
return(
<div>
{this.state.text}
</div>
)
}
}
export default Barista;
As by this point I am completely stuck, I don't have anything for the machine component yet. While I have no doubt that I have a multitude of problems here, my main problem is when a user presses a button in the customer component how to change the text in the barista component. Is there something simple I am missing or am I completely off the mark?
You're falling victim to the most classic of all React problems. Instead of reacting to state changes, you are only rendering the view based on an initial state.
This super simple change will fix your problem:
Now when your parent state changes from clicking the button in
Customer
theBarista
render method will show the updated message becausethis.props.value
has changed.Note: your props aren't named correctly.. in
App
you called itcoffeeSelect
:.. but in
Barista
you called itthis.props.coffee
so make sure to name your props the same. InApp
it should be:EDIT: Fixed the problem with having to press the button twice.