[7天學會ReactJS] Day 5. 實作購買功能 — State

Andy Tsai
ReactMaker
Published in
9 min readSep 12, 2017

同學們好,今天要講解的是React中很重要的state,Day 4時有使用到statesetState來讓<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>也就開啟囉。

本日目標

學會了statesetState後就馬上來實作購買功能吧。

  1. 點擊購買按鈕後將商品加入購物車。
  2. 購物車顯示購買商品。

1. 購物車按鈕顯示購買數量

[程式碼]

state = {
modal: false,
album: AlbumJson,
cart: [],
}
...<Button color="primary" onClick={this.toggle}>購物車({this.state.cart.length})</Button>

這個步驟我們先在state新增一個cart的空陣列來初始化購買物品,並且使用Array.length在購物車按鈕旁顯示購買物品數量。

[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 狀態。

[Array — push]

商品購買按鈕加入onClick來觸發addToCart函式,並將product傳進去。

當點擊購買按鈕後,購物車數量就會跟著更新囉。

3. 商品限定只能買一個

[程式碼]

上個步驟我們實作了購買功能,假如我們限制使用者每個商品最多只能買一個的話,該怎麼做呢?

<Button
disabled={this.state.cart.find(item => item.id === product.id)}
color="secondary"
onClick={() => this.addToCart(product)}
>

我們利用Array.find來查詢商品是否存在於購物車中,假如存在的話就disabled購買按鈕,就可以達到限制只能買一筆的目的囉!

[Array — find]

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得到加總價格。

[Array.reduce]

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,敬請期待。

--

--