import * as React from 'react'
const { useContext, useReducer, createContext } = React
//一定要返回狀態
function reducerInAction(state, action) {
if (typeof action.reducer == 'function') {
return action.reducer(state)
}
return state
}
//公用的資料處理
export default function createStore(params) {
const { initialState = {}, reducer
} = {
...params,
reducer: reducerInAction
}
//實際是由createContext所有狀態版本的管理
const Appcontext = createContext()
const middleWareReducer = (lastState, action) => {
//更新資料
let netxState = reducer(lastState, action)
store._state = netxState
return netxState
}
const store = {
_state: initialState,
dispatch: undefined,
getState: () => {
return store._state
},
useContext: () => {
return useContext(Appcontext)
}
}
//資料包裹返回
const Provider = props => {
const [state, dispatch] = useReducer(middleWareReducer, initialState)
if (!store.dispatch) {
store.dispatch = async (action) => {
if (typeof action === 'function') {
await action(dispatch, store.getState())
} else {
dispatch(action)
}
}
}
return <Appcontext.Provider {...props} value={state} />
}
return {
Provider,
store
}
}
複製程式碼
引用案例
import * as React from 'react'
import HooksRedux from './HooksRedux'
const {
Provider,
store
} = HooksRedux({
initialState: { name: '微微', age: 0 }
})
const Home = () => {
const state = store.useContext()
return (
< div >
Home元件Age: {state.age}
<br />
<Button />
</div >
)
}
//同步請求
const actionOfAdd = () => {
return {
type: 'addCount',
reducer(state) {
return {
...state,
age: state.age + 1
}
}
}
}
function timeOutAdd(a) {
return new Promise(cb => setTimeout(() => cb(a - 1), 500))
}
//非同步請求
const actionAsyncOfDelete = () => async (dispatch, ownState) => {
const age = await timeOutAdd(ownState.age)
dispatch({
type: 'addCount',
reducer(state) {
return {
...state,
age
}
}
})
}
//出發請求
const Button = () => {
function handleAdd() {
//返回給dispatch的是一個物件 store.dispatch(actionOfAdd())
}
function handleAsyncDelete() {
//返回給dispatch的是一個物件 store.dispatch(actionAsyncOfDelete())
}
return <>
<button onClick={handleAdd} >點選增加</button>
<button onClick={handleAsyncDelete} >點選非同步減少</button>
</>
}
const WarpHome = () => {
return (
<Provider>
<Home />
</Provider>
)
}
export default WarpHome
複製程式碼