[7天學會ReactJS] Day 5. 實作購買功能 — State
同學們好,今天要講解的是React中很重要的state
,Day 4時有使用到state
和setState
來讓<Modal>
彈出來,現在來更加詳細的講解一下state
吧!
state
React要動態呈現畫面,最常用到的就是state,它是Component自己的狀態。
例如購物車視窗要讓它開關,我們就可以有”開啟”和”關閉”兩種狀態,並且在這兩種狀態之間進行切換。React的state
就是用來儲存這種變化狀態的,並用 this.state
來存取 state
。
state = {
modal: false,
}...// modal = false,關閉
<Modal isOpen={this.state.modal}>
</Modal>
Component產生時宣告state
有一個modal
狀態為false,<Modal>
則使用this.state.modal
預設關閉購物車視窗。
setState
當我們呼叫setState
函式,React會更新Component的state
,並且重新呼叫 render
函式,然後把最新的狀態呈現在畫面上。
特別注意到的是,我們要修改Component的state
時,不能直接使用this.state.xxx = XXX 這種方式進行修改,因為這樣做的話React不知道你更新了state
,畫面也就不會進行更新,這也是新手最常遇到的雷喔。所以一定要使用React提供的setState
方法來進行更新喔。
setState
傳入參數為object或function。
toggle = () => {
this.setState({
modal: true,
});
}...// modal = true,開啟
<Modal isOpen={this.state.modal}>
</Modal>
我們使用setState
更新state,傳入一個object為modal: true
,這就是我們要將modal從false更新為true。
此時React呼叫render
函式將最新狀態呈現在畫面上,因此<Modal>
也就開啟囉。
本日目標
學會了state
和setState
後就馬上來實作購買功能吧。
- 點擊購買按鈕後將商品加入購物車。
- 購物車顯示購買商品。
1. 購物車按鈕顯示購買數量
[程式碼]
state = {
modal: false,
album: AlbumJson,
cart: [],
}...<Button color="primary" onClick={this.toggle}>購物車({this.state.cart.length})</Button>
這個步驟我們先在state
新增一個cart
的空陣列來初始化購買物品,並且使用Array.length在購物車按鈕旁顯示購買物品數量。
目前顯示購買物品為0。
2. 實作加入購物車函式
[程式碼]
addToCart = (product) => {
const cart = this.state.cart;
cart.push(product);
this.setState({
cart
});
}...<Button color="secondary" onClick={() => this.addToCart(product)}>購買</Button>
實作了一個addToCart
函式,並傳入目前點擊到的商品資訊,使用Array的push將商品資訊加入cart
陣列,最終使用setState
來更新cart
狀態。
商品購買按鈕加入onClick
來觸發addToCart
函式,並將product
傳進去。
當點擊購買按鈕後,購物車數量就會跟著更新囉。
3. 商品限定只能買一個
[程式碼]
上個步驟我們實作了購買功能,假如我們限制使用者每個商品最多只能買一個的話,該怎麼做呢?
<Button
disabled={this.state.cart.find(item => item.id === product.id)}
color="secondary"
onClick={() => this.addToCart(product)}
>
我們利用Array.find
來查詢商品是否存在於購物車中,假如存在的話就disabled
購買按鈕,就可以達到限制只能買一筆的目的囉!
4. 顯示購物車物品
[程式碼]
還記得我們購物車視窗中的購買物品還是寫死的嗎,現在要把它從this.state.cart
呈現在畫面上喔。
{
this.state.cart.map((item, index) => (
<tr>
<th scope="row">{index + 1}</th>
<td>{item.title}</td>
<td>{item.price}</td>
</tr>
))
}
一樣使用Array.map
產生多個<tr>
來顯示購買物品。
{index + 1}
顯示這是第幾個購買物品。
{item.title}
顯示購買物品的標題。
{item.price}
則是購買物品的價格。
5. 計算總價
[程式碼]
購買物品已經顯示在畫面上了,現在來把價格加總起來吧!
import { Container, Row, Col, Jumbotron, Button, Card, CardImg, CardBlock, CardTitle, CardSubtitle, CardText, Badge, Modal, ModalHeader, ModalBody, ModalFooter, Table, Alert } from 'reactstrap';...<Alert color="success" className="text-right">
總價:
{this.state.cart.reduce((acc, item) => (acc += item.price), 0)}
元
</Alert>
透過Reactstrap
的<Alert>
來美化總價呈現。
加總可以利用Array.reduce
來達到快速加總的效果,且簡化程式碼。
原理為初始值為0,持續累加item.price
得到加總價格。
6. 刪除購買物品
[程式碼]
我們是不是還缺少點什麼呢?來實作刪除購買物品吧。
deleteCartItem = (index) => {
const cart = this.state.cart;
cart.splice(index, 1);
this.setState({
cart
});
}...<td><Button color="danger" onClick={() => this.deleteCartItem(index)}>X</Button>{' '}</td>
針對每列購買物品加入一顆刪除按鈕,onClick
時呼叫deleteCartItem
函式,並傳入該購買物品的index
實作deleteCartItem
函式,使用Array.splice
來刪除該index
的值,也就是把該index
的購買物品移除,達到刪除的目的。
最後將已刪除購買物品的cart
更新到state
,畫面就會跟著更新了。
7. 沒有購物商品時,停用結帳按鈕
[程式碼]
沒有購買商品卻可以點擊結帳按鈕,似乎有點不合理。那就來把它停用掉吧。
<Button
disabled={this.state.cart.length === 0}
color="primary"
onClick={this.toggle}
>
結帳
</Button>
這裡可以簡單的判斷this.state.cart
的數量為0時,disabled
掉結帳按鈕。
8. 點擊結帳顯示總價
[程式碼]
加油加油,到了最後一步囉,把結帳按鈕功能做出來吧!
checkout = (totalPrice) => {
alert(`已從您的信用卡中扣除${totalPrice}元!`);
}...const totalPrice = this.state.cart.reduce((acc, item) => (acc += item.price), 0);...<Button
disabled={cart.length === 0}
color="primary"
onClick={() => this.checkout(totalPrice)}
>
結帳
</Button>
將結帳按鈕的onClick
修改成呼叫this.checkout
函式,並傳入總價,因為總價有兩個地方會使用,因此將它做成變數供大家使用。
checkout
函式先簡單地用alert
將總價顯示在畫面上吧!!
好的,到這裡為止我們已經完成購物網站的所有功能囉。
Day 6會介紹props
和切Component
,敬請期待。