引子
上次我们说到React Native Redux Typescript使用 redux-thunk or redux-saga,相信对于刚入门的同学来说,看完博客感觉理解起来亚历山大。
那么,我们需要一个可以完整实现redux多种操作,并且简单易懂的封装好的框架。
难道真的有这样的框架吗?
对于要解决最一线,最急切的需求。这个可以有,这个必须有。
web页面快速上手
点这里:https://github.com/dvajs/dva-docs/blob/master/v1/zh-cn/getting-started.md
快速上手
通过上面的快速介绍文档,我们可以了解到 dva框架是如此的方便快捷已与学习和应用。
最小化实现dva Dva-Core
添加依赖包引用
执行
1 2
| yarn add dva-core redux-logger yarn add -D @types/redux-logger
|
定义dva-core “声明”
严格意义上将,我这个定义的不是声明,是对dva-core封装了一遍
新建文件 utils/dva.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| import React from 'react'; import { Provider, connect } from 'react-redux'; let {create} = require("dva-core"); export { connect }; export interface Options { models: Model[]; extraReducers?: any; initialState: any; onError: (e: any) => void; onAction: any[]; }
export function dva(options: Options) { const app = create(options); options.models.forEach((model: Model) => app.model(model)); app.start(); const store = app._store;
app.start = (container: any) => () => <Provider store={store}>{container}</Provider>; app.getStore = () => store;
return app; }
import { Reducer, Action, ReducersMapObject, Dispatch, } from 'redux';
export interface EffectsCommandMap { put: <A extends Action>(action: A) => any; call: Function; select: Function; take: Function; cancel: Function; [key: string]: any; } export interface EffectsMapObject { [key: string]: Effect | EffectWithType; } export interface ReducerEnhancer { (reducer: Reducer<any>): void; } export interface SubscriptionAPI { dispatch: Dispatch<any>; } export type ActionWithPayload = {action: Action, payload: any}; export type EffectType = 'takeEvery' | 'takeLatest' | 'watcher' | 'throttle'; export type EffectWithType = [Effect, { type: EffectType }]; export type Effect = (action: ActionWithPayload, effects: EffectsCommandMap) => void; export type ReducersMapObjectWithEnhancer = [ReducersMapObject, ReducerEnhancer]; export type Subscription = (api: SubscriptionAPI, done: Function) => void; export interface SubscriptionsMapObject { [key: string]: Subscription; } export interface Model { namespace: string; state?: any; reducers?: ReducersMapObject | ReducersMapObjectWithEnhancer; effects?: EffectsMapObject; subscriptions?: SubscriptionsMapObject; }
|
为了方便看到异步效果,我们新建个通用工具
新建文件 utils/index.ts
1
| export const delay = (time:any) => new Promise(resolve => setTimeout(resolve, time))
|
定义Model
新建 models/count.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import {delay} from '../utils/index'; import { Model } from "../utils/dva"; type countState=number export default { namespace: 'count', state: 0 as countState, reducers: { add(state:countState) { return state + 1; }, minus(state:countState) { return state - 1; }, }, effects: { *addWithDelay(action, { call, put }) { console.log('===================================='); console.log(action); console.log('===================================='); console.log('===================================='); console.log(call); console.log('===================================='); console.log('===================================='); console.log(put); console.log('===================================='); yield call(delay, 1000); yield put({ type: 'add' }); } }, } as Model;
|
然后新建展示页面 routes/Home.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| import React, { Component } from "react"; import { StyleSheet, Text, View, Button } from "react-native";
import {connect} from '../utils/dva'; interface Props { count:number, dispatch?:any } interface State { } class App extends Component<Props, State> { render() { return ( <View style={styles.container}> <Text style={styles.text}> Welcome to React Native! </Text> <Text style={styles.text}> Count: { this.props.count } </Text> <Button title="+" onPress={() => { this.props.dispatch({ type: 'count/add' }); }} /> <Button title="-" onPress={() => { this.props.dispatch({ type: 'count/minus' }); }} /> <Button title="+ async" onPress={() => { this.props.dispatch({ type: 'count/addWithDelay' }); }} /> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center", backgroundColor: "#F5FCFF", } , text: { fontSize: 20, textAlign: "center", margin: 10, }, });
function mapStateToProps(state:any) { return { count: state.count, }; } export default connect(mapStateToProps)(App);
|
初始化dva
新建 index.tsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import React from 'react'; import { AppRegistry, AsyncStorage } from 'react-native'; import {createLogger} from 'redux-logger'; import {dva}from './utils/dva' import count from './models/count' import Home from './routes/Home'; const app = dva({ initialState: {}, models: [count], extraReducers: {}, onError(e: any) { console.error('onError', e); }, onAction: [createLogger({collapsed: true})],
}); const App = app.start(<Home />) export default App;
|
然后我们运行项目看看效果: