diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..8df53fe
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+"presets": ["react-native"]
+}
\ No newline at end of file
diff --git a/.flowconfig b/.flowconfig
index 168c3c6..3b261e2 100644
--- a/.flowconfig
+++ b/.flowconfig
@@ -1,7 +1,7 @@
[ignore]
# We fork some components by platform.
-.*/*.android.js
+.*/*[.]android.js
# Ignore templates with `@flow` in header
.*/local-cli/generator.*
@@ -48,11 +48,11 @@ suppress_type=$FlowIssue
suppress_type=$FlowFixMe
suppress_type=$FixMe
-suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-9]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
-suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-9]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
+suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-3]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
+suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-3]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
unsafe.enable_getters_and_setters=true
[version]
-^0.29.0
+^0.33.0
diff --git a/__tests__/example-test.js b/__tests__/example-test.js
new file mode 100644
index 0000000..e09de39
--- /dev/null
+++ b/__tests__/example-test.js
@@ -0,0 +1,6 @@
+import example from '../src/models/example';
+
+test('it should save', () => {
+ expect(example.reducers['example/save']({}, { payload: { a: 1 }}))
+ .toEqual({ a: 1 });
+});
diff --git a/index.android.js b/index.android.js
index be175e3..d7a5e75 100644
--- a/index.android.js
+++ b/index.android.js
@@ -1,53 +1 @@
-/**
- * Sample React Native App
- * https://github.com/facebook/react-native
- * @flow
- */
-
-import React, { Component } from 'react';
-import {
- AppRegistry,
- StyleSheet,
- Text,
- View
-} from 'react-native';
-
-class DvaExampleReactNative extends Component {
- render() {
- return (
-
-
- Welcome to React Native!
-
-
- To get started, edit index.android.js
-
-
- Double tap R on your keyboard to reload,{'\n'}
- Shake or press menu button for dev menu
-
-
- );
- }
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: '#F5FCFF',
- },
- welcome: {
- fontSize: 20,
- textAlign: 'center',
- margin: 10,
- },
- instructions: {
- textAlign: 'center',
- color: '#333333',
- marginBottom: 5,
- },
-});
-
-AppRegistry.registerComponent('DvaExampleReactNative', () => DvaExampleReactNative);
+import './src';
diff --git a/index.ios.js b/index.ios.js
index bd97e32..d7a5e75 100644
--- a/index.ios.js
+++ b/index.ios.js
@@ -1,73 +1 @@
-/**
- * Sample React Native App
- * https://github.com/facebook/react-native
- * @flow
- */
-
-import React, { Component } from 'react';
-import {
- AppRegistry,
- StyleSheet,
- Text,
- View,
- Button,
- TouchableHighlight,
-} from 'react-native';
-
-import dva, { connect } from 'dva/mobile';
-
-function delay(timeout) {
- return new Promise(resolve => {
- setTimeout(resolve, timeout);
- });
-}
-
-const app = dva();
-app.model({
- namespace: 'count',
- state: 0,
- reducers: {
- add(state) { return state + 1 },
- },
- effects: {
- *addDelay(action, { call, put }) {
- yield call(delay, 1000);
- yield put({ type: 'add' });
- },
- },
- subscriptions: {
- setup({ dispatch }) {
- dispatch({type: 'add'});
- },
- },
-});
-
-const App = connect(({ count }) => ({ count }))((props) => {
- const { dispatch, count } = props;
- return (
-
-
- Count: { count }
-
- { dispatch({ type: 'count/add' }) }}>
- Add
-
- { dispatch({ type: 'count/addDelay' }) }}>
- Delay Add
-
-
- );
-});
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: '#F5FCFF',
- },
-});
-
-app.router(() => );
-
-AppRegistry.registerComponent('DvaExampleReactNative', () => app.start());
+import './src';
diff --git a/package.json b/package.json
index 3208db4..4ebdd55 100644
--- a/package.json
+++ b/package.json
@@ -3,12 +3,23 @@
"version": "0.0.1",
"private": true,
"scripts": {
- "start": "node node_modules/react-native/local-cli/cli.js start"
+ "start": "node node_modules/react-native/local-cli/cli.js start",
+ "test": "jest"
},
"dependencies": {
"dva": "1.1.0",
"react": "15.3.2",
"react-dom": "15.3.2",
"react-native": "0.36.0"
+ },
+ "jest": {
+ "preset": "jest-react-native"
+ },
+ "devDependencies": {
+ "babel-jest": "16.0.0",
+ "babel-preset-react-native": "1.9.0",
+ "jest": "16.0.2",
+ "jest-react-native": "16.1.0",
+ "react-test-renderer": "15.3.2"
}
}
diff --git a/src/components/CounterText.js b/src/components/CounterText.js
new file mode 100644
index 0000000..cc88b2c
--- /dev/null
+++ b/src/components/CounterText.js
@@ -0,0 +1,18 @@
+import React, { Component } from 'react';
+import {
+ Text
+} from 'react-native';
+
+var CounterText = React.createClass({
+
+ render: function() {
+ return (
+
+ Count: { this.props.count }
+
+ );
+ }
+
+});
+
+module.exports = CounterText;
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..26b933b
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,17 @@
+/**
+ * Sample React Native App
+ * https://github.com/facebook/react-native
+ * @flow
+ */
+import React, { Component } from 'react';
+import {
+ AppRegistry
+} from 'react-native';
+import dva from 'dva/mobile';
+import Counter from './pages/Counter';
+
+const app = dva();
+app.model(require('./models/count.js'));
+app.router(() => );
+
+AppRegistry.registerComponent('DvaExampleReactNative', () => app.start());
diff --git a/src/models/count.js b/src/models/count.js
new file mode 100644
index 0000000..eab6a03
--- /dev/null
+++ b/src/models/count.js
@@ -0,0 +1,23 @@
+function delay(timeout) {
+ return new Promise(resolve => {
+ setTimeout(resolve, timeout);
+ });
+}
+module.exports = {
+ namespace: 'count',
+ state: 0,
+ reducers: {
+ add(state) { return state + 1 },
+ },
+ effects: {
+ *addDelay(action, { call, put }) {
+ yield call(delay, 1000);
+ yield put({ type: 'add' });
+ },
+ },
+ subscriptions: {
+ setup({ dispatch }) {
+ dispatch({type: 'add'});
+ },
+ },
+};
diff --git a/src/models/example.js b/src/models/example.js
new file mode 100644
index 0000000..c29639c
--- /dev/null
+++ b/src/models/example.js
@@ -0,0 +1,27 @@
+
+export default {
+
+ namespace: 'example',
+
+ state: {},
+
+ subscriptions: {
+ setup({ dispatch, history }) {
+ },
+ },
+
+ effects: {
+ *fetchRemote({ payload }, { call, put }) {
+ },
+ },
+
+ reducers: {
+ fetch(state, action) {
+ return { ...state, ...action.payload };
+ },
+ 'example/save'(state, action) {
+ return { ...action.payload };
+ },
+ },
+
+}
diff --git a/src/pages/Counter.js b/src/pages/Counter.js
new file mode 100644
index 0000000..6a4500b
--- /dev/null
+++ b/src/pages/Counter.js
@@ -0,0 +1,36 @@
+import React, { Component } from 'react';
+import {
+ StyleSheet,
+ Text,
+ View,
+ Button,
+ TouchableOpacity,
+} from 'react-native';
+import { connect } from 'dva/mobile';
+import CounterText from '../components/CounterText';
+
+const App = connect(({ count }) => ({ count }))((props) => {
+ const { dispatch, count } = props;
+ return (
+
+
+ { dispatch({ type: 'count/add' }) }}>
+ Add
+
+ { dispatch({ type: 'count/addDelay' }) }}>
+ Delay Add
+
+
+ );
+});
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: '#F5FCFF',
+ },
+});
+
+export default App;
diff --git a/src/services/example.js b/src/services/example.js
new file mode 100644
index 0000000..bbf54e3
--- /dev/null
+++ b/src/services/example.js
@@ -0,0 +1,5 @@
+import request from '../utils/request';
+
+export async function query() {
+ return request('/api/users');
+}
diff --git a/src/utils/request.js b/src/utils/request.js
new file mode 100644
index 0000000..c808422
--- /dev/null
+++ b/src/utils/request.js
@@ -0,0 +1,30 @@
+import fetch from 'dva/fetch';
+
+function parseJSON(response) {
+ return response.json();
+}
+
+function checkStatus(response) {
+ if (response.status >= 200 && response.status < 300) {
+ return response;
+ }
+
+ const error = new Error(response.statusText);
+ error.response = response;
+ throw error;
+}
+
+/**
+ * Requests a URL, returning a promise.
+ *
+ * @param {string} url The URL we want to request
+ * @param {object} [options] The options we want to pass to "fetch"
+ * @return {object} An object containing either "data" or "err"
+ */
+export default function request(url, options) {
+ return fetch(url, options)
+ .then(checkStatus)
+ .then(parseJSON)
+ .then((data) => ({ data }))
+ .catch((err) => ({ err }));
+}