Let's make an ATM app! You will practice the dark art of manipulating components in real time. You will create two components of the same class which will work independently of each other.
Fork and Clone this repo, and run npm install
from inside it. The repo already includes a partial React app. To launch the app, run npm start
.
-
Pass a
name
property to eachAccount
component, one for "Checking", the other for "Savings". These will be used and accessed asprops
for our component. Remember: Props are immutable, that is, once they are declared, they cannot be changed while the application is running.Click for code:
<div> <Account name="Checking"/> <Account name="Savings"/> </div>
-
Use the property you set in
App.js
to add the name of the account to the<h2>
.Click for code:
<div className="account"> //this.props.name is referring to the name property we assigned the App component in App.js <h2>{this.props.name}</h2> <div className="balance">$0</div> <input type="text" placeholder="enter an amount" /> <input type="button" value="Deposit" /> <input type="button" value="Withdrawl" /> </div>
Save your work. You should see two components named Checking and Savings. You're getting there!
-
Add a
balance
property tostate
, and set to 0 initially, in the Account component.Click for code:
class Account extends Component { constructor(props){ super(props) this.state = { balance: 0 } } }
-
Set a
ref
property on the text field, which is a callback function to save a reference to that text field in ourAccount
object. This is one way we can access the data in the field later when we want to know what values to add/subtract from our account. You can also try to figure out how to do it using the react form way, which we will be going into depth alot more tomorrow, but if you get blocked go ahead and use theref
.Hint:
<input type="text" placeholder="enter an amount" ref={(input) => this.inputBox = input} />
-
When the
Deposit
button is clicked, you should add the amount entered in the text field to the balanceClick for code walkthrough:
a. Add a click handler in your input tags in our JSX return block:<input type="button" value="Deposit" onClick={this.handleDepositClick} />
b. Define a click handler method within the
Account
classhandleDepositClick(e) { // It is good practice to still prevent default behavior e.preventDefault(); // set a local variable to the amount entered in the text box. const amount = parseInt(this.inputBox.value); // set a local variable to the new balance based off of the original balance + amount const newBalance = this.state.balance + amount; // set the balance to the newBalance using the setState method (necessary) this.setState({ balance: newBalance }) // empty out the text box in this component this.inputBox.value = ''; }
-
When the
Withdraw
button is clicked, you should deduct the amount entered in the text field to the balance. You should not be able to withdraw more than the current balanceClick for hint:
Try to mirror the functionality of the Deposit function above.
-
If the current balance is 0, you should add a class of
zero
to the<div className="balance">
. You can complete these computations in the render method, but before the JSX portion is returned.Click for code walkthrough:
In the Account.js render method:// set the default class to `balance` for the balanceClass. const balanceClass = 'balance'; // if the balance is 0, then add the class zero to balanceClass if (this.state.balance === 0) { balanceClass += ' zero'; }
Replace the hardcoded `balance` class with the balanceClass variable in your return jsx code block:
<div className={balanceClass}>$0</div>
- Handling an edge case
- As it stands, our app breaks if we hit Deposit or Withdraw on an empty form. Or if we put letters in there! How can we update our functionality to avoid this problem?
- hint: Don't assume NaN behaves as you might expect :)
- Refactor the common code out of handleWithdrawlClick and handleDepositClick into a helper function or two.
- Create a Transfer form that can transfer funds from Checking to Savings, or Savings to Checking!