React Native开发经验集React Native开发

React Native Dva Typescript 柳暗花明

2018-07-22  本文已影响21人  ArthurWang

引子

上次我们说到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

添加依赖包引用

执行

yarn add dva-core  redux-logger
yarn add -D  @types/redux-logger

定义dva-core “声明”

严格意义上将,我这个定义的不是声明,是对dva-core封装了一遍

新建文件 utils/dva.tsx

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

export const delay = (time:any) => new Promise(resolve => setTimeout(resolve, time))

定义Model

新建 models/count.ts

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

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

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
上一篇下一篇

猜你喜欢

热点阅读