React Native Dva Typescript 柳暗花明又一村

引子

上次我们说到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: {},
// models:[m],
onError(e: any) {
console.error('onError', e);
},
onAction: [createLogger({collapsed: true})],

});
const App = app.start(<Home />)
export default App;

然后我们运行项目看看效果:

react-native-redux-saga-dva-typescript-20187213142