前篇我們已經完成咖啡與咖啡豆兩樣商品的搬遷,今天我們將蛋糕的部分也移植過來我們 React 的專案裡面,也順便加深使用的印象。
還記得怎麼處理嗎?
Start from slice
沒錯,就是從 slice 開始,分類分得好,搬檔案就改得少,一樣我們於相同的路徑下新增一樣的slice,如下:
// src/features/slices/cakeSlice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
numOfCake: 20
}
const cakeSlice = createSlice({
name: 'cake',
initialState,
reducers: {
cakeOrdered: (state, action) => {
state.numOfCake = state.numOfCake - parseInt(action.payload.qty)
return state;
},
cakeRestocked: (state, action) => {
state.numOfCake = state.numOfCake + parseInt(action.payload.qty)
return state;
},
}
})
// 方便辨識的處理
export const selectCake = (state) => state.cake;
export const { cakeOrdered, cakeRestocked } = cakeSlice.actions
export default cakeSlice.reducer
一樣不要忘記要回 store 做調整:
// src/features/store.js
import { configureStore } from '@reduxjs/toolkit'
import cakeSlice from './slices/cakeSlice'
import coffeeBeanSlice from './slices/coffeeBeanSlice'
import coffeeSlice from './slices/coffeeSlice'
const store = configureStore({
reducer: {
coffee: coffeeSlice,
coffeeBean: coffeeBeanSlice,
cake: cakeSlice,
}
})
export default store
基本上功能搬遷就已經完成了。
再來我們來處理畫面的 component,其實你會發現結構上都是一樣的,那麼何不用複製貼上的被動技能完成再做調整勒,這時候你就會發現有做檔案拆分的好處了吧!拆分有拆分的好處喔~
我們移動到 components 的資料夾下新增一個 CakeBlock.jsx 的檔案開始以下表演:
// src/components/CakeBlock.jsx
import React, { useRef } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { cakeOrdered, cakeRestocked, selectCake } from '../features/slices/cakeSlice'
const CakeBlock = () => {
const cake = useSelector(selectCake)
const dispatch = useDispatch()
// 購買
const cakeOrderQtyRef = useRef(null)
const cakeOrderMoneyRef = useRef(null)
// 進貨
const cakeRestockQtyRef = useRef(null)
const cakeRestockMoneyRef = useRef(null)
// 購買送出
const doOrderCake = () => {
const sendData = {
qty: cakeOrderQtyRef.current.value,
money: cakeOrderMoneyRef.current.value
}
dispatch(cakeOrdered(sendData))
}
// 進貨送出
const doRestockCake = () => {
const sendData = {
qty: cakeRestockQtyRef.current.value,
money: cakeRestockMoneyRef.current.value
}
dispatch(cakeRestocked(sendData))
}
return (
<div>
<h4>蛋糕存量 {cake.numOfCake}</h4>
<fieldset>
<legend>蛋糕購買</legend>
<div>
<label htmlFor="cakeOrderQty">數量</label>
<input id="cakeOrderQty" type="number" ref={cakeOrderQtyRef} />
</div>
<div>
<label htmlFor="cakeOrderMoney">價錢</label>
<input id="cakeOrderMoney" type="number" ref={cakeOrderMoneyRef} />
</div>
<button onClick={doOrderCake}>
購買
</button>
</fieldset>
<fieldset>
<legend>蛋糕進貨</legend>
<div>
<label htmlFor="cakeRestockQty">數量</label>
<input id="cakeRestockQty" type="number" ref={cakeRestockQtyRef} />
</div>
<div>
<label htmlFor="cakeRestockMoney">價錢</label>
<input id="cakeRestockMoney" type="number" ref={cakeRestockMoneyRef} />
</div>
<button onClick={doRestockCake}>
進貨
</button>
</fieldset>
</div>
)
}
export default CakeBlock
完成後,一樣於 App 內引入剛才的 component,如下:
// src/App.jsx
import CakeBlock from "./components/CakeBlock"
import CoffeeBeanBlock from "./components/CoffeeBeanBlock"
import CoffeeBlock from "./components/CoffeeBlock"
function App() {
return (
<div className="container">
<h1>Restaurant Record</h1>
<CoffeeBlock/>
<CoffeeBeanBlock/>
<CakeBlock/>
</div>
)
}
export default App
此時,你的畫面應該會多出蛋糕購買、蛋糕進貨兩個區塊,並可以看到蛋糕的庫存會因為你的操作而有增減。
恭喜你又完成了蛋糕商品的功能,以此類推,你應該可以按照相同的步驟去創造出更多不同的商品,透過兩次的練習,應該已經處於駕輕就熟的階段了吧!
下一篇我們將資金的部分也搬遷進來。