今天不刻介面,今天來導入我們的狀態管理,管理我們未來會遇到的奇形怪狀的狀態!我本來想說直接引入Redux,因為Redux並不是React專用,但後來發現我們使用typescript,好像定義檔只有react-redux才有,我又不想花很多時間在寫定義檔,原因是我對撰寫定義檔並不熟悉呵呵。補充:Redux是Typescript寫的,可以直接拿來用就好,當下沒注意到寫完才發現。
總而言之,我其實可以寫一個事件觸發器直接當作類似Redux的結構進行更新,但考慮很久我還是直接寫一個Redux就好了,因為我印象中簡易版本Redux並不會特別複雜。
一搬我們在使用Redux的時候簡易樣子大會是這樣。
透過CreateStore建出一個封裝好的Store,我們可以對Store取狀態,但要修改狀態必須透過dispatch派發。
import { createStore } from 'redux';
const store = createStore()
const state = store.getState()
store.dispatch('xxxx')
於是我們開始打造吧!
以下就是大致上我們基本的樣子,透過createStore把我們的Reducer包裝至我們dispatch內,這樣我們派發後,Store會幫我們把State經過我們的Reducer產生出我們要的變化,並把舊的State取代。
我們可以透過getState()取得新的狀態
export function createStore(initialReducer: Function, initalState = {}): Store {
let reducer = initialReducer
let state = reducer(initalState, { type: '__INIT__' })
return {
getState() {
return state
},
dispatch(action: Action): void {
state = reducer(state, action)
}
}
}
再來是因為我們要取得新的狀態,其他組件並不知道我們目前的狀態更新了,因此需要Observer的概念,讓組件監聽著我們的Store。
其實就很像是EventEmitter那種的觸發器而已,相當容易理解,我覺得比較精巧的部分是,他返回一個function可以直接unSubscribe這點讓我滿驚訝的,我從來沒想過可以這樣寫,學到了一課!
export function createStore(initialReducer: Function, initalState = {}): Store {
let reducer = initialReducer
let subscribes: Array<Function> = []
let state = reducer(initalState, { type: '__INIT__' })
return {
getState() {
return state
},
dispatch(action: Action): void {
state = reducer(state, action)
subscribes.forEach(subscriber => subscriber())
},
subscribe(listener: Function): Function {
subscribes.push(listener)
return () => {
subscribes = subscribes.filter(subscriber => subscriber !== listener)
}
}
}
}
我其實已經不知道這怎麼翻譯的,我這是看參考文章及參考Redux原碼的。
這是指我們在createStore可傳入enhancer用來很像是middleware的概念,但其實Redux有另外一套middleware的方法,讓我們有機會可以在變化前後縞一些事,像是log資料等等。
export function createStore(initialReducer: Function, initalState = {}, enhancer?: Function): Store {
if (enhancer) {
return enhancer(createStore)(initialReducer, initalState)
}
let reducer = initialReducer
let subscribes: Array<Function> = []
let state = reducer(initalState, { type: '__INIT__' })
return {
getState() {
return state
},
dispatch(action: Action): void {
state = reducer(state, action)
subscribes.forEach(subscriber => subscriber())
},
subscribe(listener: Function): Function {
subscribes.push(listener)
return () => {
subscribes = subscribes.filter(subscriber => subscriber !== listener)
}
},
replaceReducer(newReducer: Function): void {
reducer = newReducer
this.dispatch({ type: '__REPLACE__' })
}
}
}
enhancer的使用大概是以下這樣使用。
let enhancer = () => {
return createStore => (reducer, initialState, enhancer) => {
const store = createStore(reducer, initialState)
function dispatch(action) {
const res = store.dispatch(action);
const newState = store.getState();
return res;
}
return {...store, dispatch}
}
}
let store = createStore(reducer, {}, enhancer)
store.getState()
store.dispatch('xxx')
接下來我們新增到我們專案吧!在非常下面的小地方!redux.js就是redux核心檔案,store是我們在新增的有的沒的。
└─src
│ App.ts
│ Game.ts
│
├─components
│ ├─elements
│ │ Animation.ts
│ │ Sprite.ts
│ │ Texture.ts
│ │ Wrapper.ts
│ │ WrapperContainer.ts
│ │ WrapperContainerCenter.ts
│ │ WrapperType.ts
│ │
│ ├─groups
│ │ Body.ts
│ │ Casino.ts
│ │ ChipBox.ts
│ │ Loading.ts
│ │ Navbottom.ts
│ │ Navtop.ts
│ │ Pokers.ts
│ │ Table.ts
│ │
│ └─objects
│ AreaBetNumber.ts
│ Bg.ts
│ Chip.ts
│ Countdown.ts
│ CountdownNumber.ts
│ Dealer.ts
│ Desk.ts
│ DeskHover.ts
│ Info.ts
│ InfoMoneyNumber.ts
│ Poker.ts
│ PokerPoint.ts
│ PokerWin.ts
│ TotalBetNumber.ts
│ WaitNextBetNotify.ts
│
├─config
│ chipType.ts
│ imagePath.ts
│ loadingPath.ts
│ pokerPoint.ts
│ pokerType.ts
│
├─loaders
│ Loader.ts
│
├─store
│ redux.ts ***
│ store.ts ***
│
└─utils
tools.ts
store裡面我們就新增我們的reducer,這邊我們單一用一個store就好了,所有東西都放在這裡面就好,為什麼呢?因為我其實對redux掌握度不夠高,我記得可以多個合併,但我很久沒有摸了。未來還是想回到React的懷抱,之後再來全面進攻R的世界。
底下還要初始化我們的狀態哦!
store.js
function reducer(state: any, action: Action) {
if (action.type === 'UPDATE_CHOOSE_CHIP') return Object.assign(state, { chip: action.payload.chip });
if (action.type === 'UPDATE_USER_BALANCE') return Object.assign(state, { balance: action.payload.balance });
return state
}
const store = createStore(reducer, {
chip: '1000',
balance: 0
})
Github
Redux in 27 lines
Redux Source