Skip to content

Commit 0bca3c3

Browse files
committed
1 parent ca28b99 commit 0bca3c3

18 files changed

+1435
-574
lines changed

.eslintrc

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"no-mixed-operators": 0,
2626
"no-use-before-define": 0,
2727
"radix": 0,
28+
"react/destructuring-assignment": 0,
2829
"react/jsx-filename-extension": 0,
2930
"react/prop-types": 0,
3031
"semi": [2, "never"]

.flowconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
5151
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
5252

5353
[version]
54-
^0.63.0
54+
^0.67.0

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,6 @@ buck-out/
5151
*/fastlane/report.xml
5252
*/fastlane/Preview.html
5353
*/fastlane/screenshots
54+
55+
# Bundle artifact
56+
*.jsbundle

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ We provide a cli for react-native-dva-starter, for more usages and infomation cl
1818

1919
The builtin router of **dva** (not **react-router v4**), doesn't support React Native, we have to integrate other router components, such as **Navigator**, **ExperimentalNavigation**, **react-native-router-flux** and **react-navigation**. Since the former two will be depreciated in flavor of **react-navigation**, which is also be recommended by official, so I choose it to be the navigator.
2020

21-
In this starter, I provide a router model to control the default action flow of **react-navigation** to workaround a known [issue](https://github.com/react-community/react-navigation/issues/271). If you don't need this, the integration will be much simpler, you can simply remove the router model and pass **routerReducer** to **extraReducer** of dva `extraReducers: { router: routerReducer }`. Read [Redux Integration](https://reactnavigation.org/docs/guides/redux) and [dva's API](https://github.com/dvajs/dva/blob/master/docs/API.md) for more information.
21+
<del>In this starter, I provide a router model to control the default action flow of **react-navigation** to workaround a known [issue](https://github.com/react-community/react-navigation/issues/271). If you don't need this, the integration will be much simpler, you can simply remove the router model and pass **routerReducer** to **extraReducer** of dva `extraReducers: { router: routerReducer }`. Read [Redux Integration](https://reactnavigation.org/docs/guides/redux) and [dva's API](https://github.com/dvajs/dva/blob/master/docs/API.md) for more information.</del>
2222

2323
Also there is another workaround for a missing feature https://github.com/react-community/react-navigation/issues/232, so I use two **StackNavigators** to contain the screens with different transition animations, you can create you own transition animations via **transitionConfig**, see https://github.com/react-community/react-navigation/pull/99
2424

android/app/src/main/AndroidManifest.xml

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2-
package="com.dvastarter"
3-
android:versionCode="1"
4-
android:versionName="1.0">
2+
package="com.dvastarter">
53

64
<uses-permission android:name="android.permission.INTERNET" />
75
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
86

9-
<uses-sdk
10-
android:minSdkVersion="16"
11-
android:targetSdkVersion="22" />
12-
137
<application
148
android:name=".MainApplication"
15-
android:allowBackup="true"
169
android:label="@string/app_name"
1710
android:icon="@mipmap/ic_launcher"
11+
android:allowBackup="false"
1812
android:theme="@style/AppTheme">
1913
<activity
2014
android:name=".MainActivity"

app/containers/Account.js

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { createAction, NavigationActions } from '../utils'
99
@connect(({ app }) => ({ ...app }))
1010
class Account extends Component {
1111
static navigationOptions = {
12-
title: 'Account',
1312
tabBarLabel: 'Account',
1413
tabBarIcon: ({ focused, tintColor }) => (
1514
<Image

app/containers/Detail.js

-5
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,13 @@ class Detail extends Component {
1212
title: 'Detail',
1313
}
1414

15-
gotoDetail = () => {
16-
this.props.dispatch(NavigationActions.navigate({ routeName: 'Detail' }))
17-
}
18-
1915
goBack = () => {
2016
this.props.dispatch(NavigationActions.back({ routeName: 'Account' }))
2117
}
2218

2319
render() {
2420
return (
2521
<View style={styles.container}>
26-
<Button text="Goto Detail" onPress={this.gotoDetail} />
2722
<Button text="Go Back" onPress={this.goBack} />
2823
</View>
2924
)

app/containers/Home.js

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { NavigationActions } from '../utils'
99
@connect()
1010
class Home extends Component {
1111
static navigationOptions = {
12-
title: 'Home',
1312
tabBarLabel: 'Home',
1413
tabBarIcon: ({ focused, tintColor }) => (
1514
<Image

app/containers/Login.js

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { Component } from 'react'
2-
import { StyleSheet, View, Text, ActivityIndicator } from 'react-native'
2+
import { StyleSheet, View, Image, ActivityIndicator } from 'react-native'
33
import { connect } from 'react-redux'
44

55
import { Button, Touchable } from '../components'
@@ -30,8 +30,11 @@ class Login extends Component {
3030
<Button text="Login" onPress={this.onLogin} />
3131
)}
3232
{!fetching && (
33-
<Touchable style={styles.close} text="Close" onPress={this.onClose}>
34-
<Text>Close</Text>
33+
<Touchable style={styles.close} onPress={this.onClose}>
34+
<Image
35+
style={styles.icon}
36+
source={require('../images/close.png')}
37+
/>
3538
</Touchable>
3639
)}
3740
</View>
@@ -47,8 +50,13 @@ const styles = StyleSheet.create({
4750
},
4851
close: {
4952
position: 'absolute',
50-
right: 20,
51-
top: 40,
53+
right: 10,
54+
top: 30,
55+
},
56+
icon: {
57+
width: 24,
58+
height: 24,
59+
tintColor: 'gray',
5260
},
5361
})
5462

app/images/close.png

2.19 KB
Loading

app/index.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ import React from 'react'
22
import { AppRegistry } from 'react-native'
33

44
import dva from './utils/dva'
5-
import Router, { routerMiddleware } from './router'
6-
5+
import Router, { routerMiddleware, routerReducer } from './router'
76
import appModel from './models/app'
8-
import routerModel from './models/router'
97

108
const app = dva({
119
initialState: {},
12-
models: [appModel, routerModel],
10+
models: [appModel],
11+
extraReducers: { router: routerReducer },
1312
onAction: [routerMiddleware],
1413
onError(e) {
1514
console.log('onError', e)

app/models/app.js

+1-8
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,7 @@ export default {
2222
yield put(createAction('updateState')({ fetching: true }))
2323
const login = yield call(authService.login, payload)
2424
if (login) {
25-
yield put(
26-
// NavigationActions.reset can't use at react-navigation 2.0.1
27-
// should use StackActions, but now is ineffective
28-
NavigationActions.reset({
29-
index: 0,
30-
actions: [NavigationActions.navigate({ routeName: 'Main' })],
31-
})
32-
)
25+
yield put(NavigationActions.back())
3326
}
3427
yield put(createAction('updateState')({ login, fetching: false }))
3528
Storage.set('login', login)

app/models/router.js

-50
This file was deleted.

app/router.js

+31-43
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import React, { PureComponent } from 'react'
22
import { BackHandler, Animated, Easing } from 'react-native'
33
import {
4-
StackNavigator,
5-
TabNavigator,
6-
TabBarBottom,
4+
createStackNavigator,
5+
createBottomTabNavigator,
76
NavigationActions,
87
} from 'react-navigation'
98
import {
10-
initializeListeners,
11-
createReduxBoundAddListener,
9+
reduxifyNavigator,
1210
createReactNavigationReduxMiddleware,
11+
createNavigationReducer,
1312
} from 'react-navigation-redux-helpers'
1413
import { connect } from 'react-redux'
1514

@@ -19,21 +18,20 @@ import Home from './containers/Home'
1918
import Account from './containers/Account'
2019
import Detail from './containers/Detail'
2120

22-
const HomeNavigator = TabNavigator(
23-
{
24-
Home: { screen: Home },
25-
Account: { screen: Account },
26-
},
27-
{
28-
tabBarComponent: TabBarBottom,
29-
tabBarPosition: 'bottom',
30-
swipeEnabled: false,
31-
animationEnabled: false,
32-
lazyLoad: false,
21+
const HomeNavigator = createBottomTabNavigator({
22+
Home: { screen: Home },
23+
Account: { screen: Account },
24+
})
25+
26+
HomeNavigator.navigationOptions = ({ navigation }) => {
27+
const { routeName } = navigation.state.routes[navigation.state.index]
28+
29+
return {
30+
headerTitle: routeName,
3331
}
34-
)
32+
}
3533

36-
const MainNavigator = StackNavigator(
34+
const MainNavigator = createStackNavigator(
3735
{
3836
HomeNavigator: { screen: HomeNavigator },
3937
Detail: { screen: Detail },
@@ -43,7 +41,7 @@ const MainNavigator = StackNavigator(
4341
}
4442
)
4543

46-
const AppNavigator = StackNavigator(
44+
const AppNavigator = createStackNavigator(
4745
{
4846
Main: { screen: MainNavigator },
4947
Login: { screen: Login },
@@ -81,39 +79,38 @@ const AppNavigator = StackNavigator(
8179
}
8280
)
8381

84-
function getCurrentScreen(navigationState) {
82+
export const routerReducer = createNavigationReducer(AppNavigator)
83+
84+
export const routerMiddleware = createReactNavigationReduxMiddleware(
85+
'root',
86+
state => state.router
87+
)
88+
89+
const App = reduxifyNavigator(AppNavigator, 'root')
90+
91+
function getActiveRouteName(navigationState) {
8592
if (!navigationState) {
8693
return null
8794
}
8895
const route = navigationState.routes[navigationState.index]
8996
if (route.routes) {
90-
return getCurrentScreen(route)
97+
return getActiveRouteName(route)
9198
}
9299
return route.routeName
93100
}
94101

95-
export const routerMiddleware = createReactNavigationReduxMiddleware(
96-
'root',
97-
state => state.router
98-
)
99-
const addListener = createReduxBoundAddListener('root')
100-
101102
@connect(({ app, router }) => ({ app, router }))
102103
class Router extends PureComponent {
103104
componentWillMount() {
104105
BackHandler.addEventListener('hardwareBackPress', this.backHandle)
105106
}
106107

107-
componentDidMount() {
108-
initializeListeners('root', this.props.router)
109-
}
110-
111108
componentWillUnmount() {
112109
BackHandler.removeEventListener('hardwareBackPress', this.backHandle)
113110
}
114111

115112
backHandle = () => {
116-
const currentScreen = getCurrentScreen(this.props.router)
113+
const currentScreen = getActiveRouteName(this.props.router)
117114
if (currentScreen === 'Login') {
118115
return true
119116
}
@@ -125,20 +122,11 @@ class Router extends PureComponent {
125122
}
126123

127124
render() {
128-
const { dispatch, app, router } = this.props
125+
const { app, dispatch, router } = this.props
129126
if (app.loading) return <Loading />
130127

131-
const navigation = {
132-
dispatch,
133-
state: router,
134-
addListener,
135-
}
136-
return <AppNavigator navigation={navigation} />
128+
return <App dispatch={dispatch} state={router} />
137129
}
138130
}
139131

140-
export function routerReducer(state, action = {}) {
141-
return AppNavigator.router.getStateForAction(action, state)
142-
}
143-
144132
export default Router

app/utils/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export { NavigationActions } from 'react-navigation'
1+
export { NavigationActions, StackActions } from 'react-navigation'
22

33
export { default as Storage } from './storage'
44

index.js

+7
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
11
import './app/index'
2+
3+
console.ignoredYellowBox = [
4+
'Warning: componentWillMount is deprecated',
5+
'Warning: componentWillReceiveProps is deprecated',
6+
'Warning: componentWillUpdate is deprecated',
7+
'Warning: isMounted(...) is deprecated',
8+
]

0 commit comments

Comments
 (0)