React-Navigation Integration with Redux
最初发布于 szhshp的第三边境研究所, 转载请注明
React-Navigation Integration with Redux
Dependencies
{
"dependencies": {
"@expo/samples": "2.1.1",
"@shoutem/ui": "0.23.6",
"expo-asset": "~1.1.0",
"expo-constants": "~1.0.2",
"expo-file-system": "~1.1.0",
"expo-font": "~1.1.0",
"na": "0.0.1-dev0",
"prop-types": "15.6.2",
"react-navigation": "^3.0.9",
"react-navigation-redux-helpers": "2.0.9",
"react-navigation/NavigationTestUtils": "3.0.9",
"react-redux": "6.0.0",
"react-test-renderer": "16.7.0",
"redux": "4.0.1"
}
}
Main Navigation Components
import React from 'react';
import { Platform } from 'react-native';
import {
createStackNavigator,
createBottomTabNavigator,
} from 'react-navigation';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { Provider, connect } from 'react-redux';
import {
reduxifyNavigator,
createReactNavigationReduxMiddleware,
createNavigationReducer,
} from 'react-navigation-redux-helpers';
import TabBarIcon from '../components/TabBarIcon';
import HomeScreen from '../screens/HomeScreen';
import ScoresScreen from '../screens/ScoresScreen';
import SearchScreen from '../screens/SearchScreen';
import SettingsScreen from '../screens/SettingsScreen';
import Colors from '../constants/Colors';
import Reducers from '../reducers';
/*
const HomeStack = ...
const SearchStack = ...
const ScoresStack = ...
const SettingsStack = ...
*/
/* Step 1: create a navigation object */
const AppNavigator = createBottomTabNavigator(
{
SearchStack,
HomeStack,
ScoresStack,
SettingsStack,
},
{
tabBarOptions: {
style: {
paddingBottom: 5,
},
activeTintColor: Colors.tintColor,
},
}
);
/* Step 2: prepare reducers */
const navReducer = createNavigationReducer(AppNavigator);
const appReducer = combineReducers({
nav: navReducer, // required, handle actions from react-navigation
reducers: Reducers, // optional, this is your reducers
});
const middleware = createReactNavigationReduxMiddleware(
'root',
state => state.nav
);
const App = reduxifyNavigator(AppNavigator, 'root');
const mapStateToProps = state => ({
state: state.nav,
});
const AppWithNavigationState = connect(mapStateToProps)(App);
const store = createStore(appReducer, applyMiddleware(middleware));
/* step 3: create store and wrap with Provider */
class Root extends React.Component {
render() {
return (
<Provider store={store}>
<AppWithNavigationState />
</Provider>
);
}
}
export default () => <Root />;
Then everything for index are done.
Reducers Example
const defaultState = {
xxx: 123,
};
const reducer = (state, actionData) => {
let rv = !state ? defaultState : state;
console.log(actionData);
switch (actionData.type) {
/* Action Item Panel */
case 'PANEL_ACTIONITEM_DISPLAY': {
return {
xxx: state.xxx + 1,
};
}
case 'PANEL_ACTIONITEM_FORM_CHANGE': {
break;
}
case 'PANEL_ACTIONNOTE_FORM_CHANGE': {
break;
}
case 'PANEL_ACTIONNOTE_REQUEST': {
break;
}
default: {
return rv;
}
}
};
export default reducer;
Actions Example
export const actionItem_ShowEditPanel = () => ({
type: 'PANEL_ACTIONITEM_DISPLAY',
});
Actual Usage in Container Components
import React from 'react';
import { ScrollView, StyleSheet, View, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux'
import * as actions from '../actions'
const mapStateToProps = state => state;
const mapDispatchToProps = dispatch => ({
showActionItemEditRow: (action, data) => dispatch(actions.actionItem_ShowEditPanel()),
})
class SearchScreen extends React.Component {
// hide header from react-navigation
static navigationOptions = {
title: null,
header: null,
};
render() {
return (
<Screen>
<TouchableOpacity onPress={this.props.showActionItemEditRow}>
<Row>
<Text>123</Text>
</Row>
</TouchableOpacity>
</Screen>
);
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(SearchScreen);