mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-03 22:44:49 +08:00
Compare commits
6 Commits
2.6.2
...
@ericvicen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
655453aed3 | ||
|
|
c4b84f1d66 | ||
|
|
69f394be5b | ||
|
|
316e4991ac | ||
|
|
805064cb5e | ||
|
|
8f199980cb |
@@ -6,12 +6,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
### Changed
|
||||
- StackNavigator.replace method no longer requires a key param. If the key is left undefined, the last screen in the stack will be replaced.
|
||||
|
||||
## [2.6.2] - [2018-07-05)(https://github.com/react-navigation/react-navigation/releases/tag/2.6.2)
|
||||
## [2.6.2] - [2018-07-06](https://github.com/react-navigation/react-navigation/releases/tag/2.6.2)
|
||||
### Changed
|
||||
- Relax vertical padding warnings on header.
|
||||
|
||||
## [2.6.1] - [2018-07-05)(https://github.com/react-navigation/react-navigation/releases/tag/2.6.1)
|
||||
## [2.6.1] - [2018-07-05](https://github.com/react-navigation/react-navigation/releases/tag/2.6.1)
|
||||
### Added
|
||||
- Warn for more invalid headerStyle properties (padding, top/right/bottom/left, position).
|
||||
|
||||
|
||||
@@ -16,6 +16,9 @@ import {
|
||||
StatusBar,
|
||||
View,
|
||||
} from 'react-native';
|
||||
|
||||
import Reactotron from 'reactotron-react-native';
|
||||
|
||||
import { SafeAreaView, createStackNavigator } from 'react-navigation';
|
||||
|
||||
import CustomTabs from './CustomTabs';
|
||||
@@ -39,6 +42,11 @@ import TabsWithNavigationFocus from './TabsWithNavigationFocus';
|
||||
import TabsWithNavigationEvents from './TabsWithNavigationEvents';
|
||||
import KeyboardHandlingExample from './KeyboardHandlingExample';
|
||||
|
||||
Reactotron.configure()
|
||||
.useReactNative()
|
||||
.connect();
|
||||
console.tron = Reactotron;
|
||||
|
||||
const ExampleInfo = {
|
||||
SimpleStack: {
|
||||
name: 'Stack Example',
|
||||
@@ -340,7 +348,9 @@ const AppNavigator = createStackNavigator(
|
||||
}
|
||||
);
|
||||
|
||||
export default AppNavigator;
|
||||
const App = () => <AppNavigator persistenceKey="yes" />;
|
||||
|
||||
export default App;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
item: {
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
"react-navigation": "link:../..",
|
||||
"react-navigation-header-buttons": "^0.0.4",
|
||||
"react-navigation-material-bottom-tabs": "0.1.3",
|
||||
"react-navigation-tabs": "^0.5.1"
|
||||
"react-navigation-tabs": "^0.5.1",
|
||||
"reactotron-react-native": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-jest": "^22.4.1",
|
||||
|
||||
@@ -4734,6 +4734,10 @@ minizlib@^1.1.0:
|
||||
dependencies:
|
||||
minipass "^2.2.1"
|
||||
|
||||
mitt@^1.1.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.1.3.tgz#528c506238a05dce11cd914a741ea2cc332da9b8"
|
||||
|
||||
mixin-deep@^1.2.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe"
|
||||
@@ -5446,6 +5450,13 @@ qs@6.5.2, qs@^6.4.0, qs@^6.5.0, qs@^6.5.1, qs@~6.5.1:
|
||||
version "6.5.2"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||
|
||||
query-string@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.1.0.tgz#01e7d69f6a0940dac67a937d6c6325647aa4532a"
|
||||
dependencies:
|
||||
decode-uri-component "^0.2.0"
|
||||
strict-uri-encode "^2.0.0"
|
||||
|
||||
querystring@0.2.0, querystring@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
||||
@@ -5758,9 +5769,9 @@ react-navigation-deprecated-tab-navigator@1.3.0:
|
||||
dependencies:
|
||||
react-native-tab-view "^0.0.77"
|
||||
|
||||
react-navigation-drawer@0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-navigation-drawer/-/react-navigation-drawer-0.3.0.tgz#641007213f0f1e1b55a0a4bb64d71df07b3e7208"
|
||||
react-navigation-drawer@0.4.3:
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/react-navigation-drawer/-/react-navigation-drawer-0.4.3.tgz#c04c94e2429b7e724801af05bd0a93a79cb27f71"
|
||||
dependencies:
|
||||
react-native-drawer-layout-polyfill "^1.3.2"
|
||||
|
||||
@@ -5871,6 +5882,18 @@ react@^16.0.0:
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
reactotron-core-client@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/reactotron-core-client/-/reactotron-core-client-2.0.0.tgz#0229e7938ed17104b846c50295ae8cb40557e83c"
|
||||
|
||||
reactotron-react-native@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/reactotron-react-native/-/reactotron-react-native-2.0.0.tgz#54d1119c6640b7e8c6c7383e482474d4cef11016"
|
||||
dependencies:
|
||||
mitt "^1.1.2"
|
||||
prop-types "^15.5.10"
|
||||
reactotron-core-client "^2.0.0"
|
||||
|
||||
read-chunk@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-2.1.0.tgz#6a04c0928005ed9d42e1a6ac5600e19cbc7ff655"
|
||||
@@ -6570,6 +6593,10 @@ stream-parser@~0.3.1:
|
||||
dependencies:
|
||||
debug "2"
|
||||
|
||||
strict-uri-encode@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
|
||||
|
||||
string-length@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed"
|
||||
|
||||
10
flow/react-navigation.js
vendored
10
flow/react-navigation.js
vendored
@@ -184,7 +184,7 @@ declare module 'react-navigation' {
|
||||
| NavigationLeafRoute
|
||||
| NavigationStateRoute;
|
||||
|
||||
declare export type NavigationLeafRoute = {
|
||||
declare export type NavigationLeafRoute = {|
|
||||
/**
|
||||
* React's key used by some navigators. No need to specify these manually,
|
||||
* they will be defined by the router.
|
||||
@@ -204,10 +204,12 @@ declare module 'react-navigation' {
|
||||
* e.g. `{ car_id: 123 }` in a route that displays a car.
|
||||
*/
|
||||
params?: NavigationParams,
|
||||
};
|
||||
|};
|
||||
|
||||
declare export type NavigationStateRoute = NavigationLeafRoute &
|
||||
NavigationState;
|
||||
declare export type NavigationStateRoute = {|
|
||||
...NavigationLeafRoute,
|
||||
...$Exact<NavigationState>,
|
||||
|};
|
||||
|
||||
/**
|
||||
* Router
|
||||
|
||||
@@ -130,7 +130,11 @@ export default function createNavigationContainer(Component) {
|
||||
}
|
||||
|
||||
_handleOpenURL = ({ url }) => {
|
||||
const parsedUrl = urlToPathAndParams(url, this.props.uriPrefix);
|
||||
const { enableURLHandling, uriPrefix } = this.props;
|
||||
if (enableURLHandling === false) {
|
||||
return;
|
||||
}
|
||||
const parsedUrl = urlToPathAndParams(url, uriPrefix);
|
||||
if (parsedUrl) {
|
||||
const { path, params } = parsedUrl;
|
||||
const action = Component.router.getActionForPathAndParams(path, params);
|
||||
@@ -199,11 +203,15 @@ export default function createNavigationContainer(Component) {
|
||||
Linking.addEventListener('url', this._handleOpenURL);
|
||||
|
||||
// Pull out anything that can impact state
|
||||
const { persistenceKey, uriPrefix } = this.props;
|
||||
const startupStateJSON =
|
||||
persistenceKey && (await AsyncStorage.getItem(persistenceKey));
|
||||
const url = await Linking.getInitialURL();
|
||||
const parsedUrl = url && urlToPathAndParams(url, uriPrefix);
|
||||
const { persistenceKey, uriPrefix, enableURLHandling } = this.props;
|
||||
let parsedUrl = null;
|
||||
let startupStateJSON = null;
|
||||
if (enableURLHandling !== false) {
|
||||
startupStateJSON =
|
||||
persistenceKey && (await AsyncStorage.getItem(persistenceKey));
|
||||
const url = await Linking.getInitialURL();
|
||||
parsedUrl = url && urlToPathAndParams(url, uriPrefix);
|
||||
}
|
||||
|
||||
// Initialize state. This must be done *after* any async code
|
||||
// so we don't end up with a different value for this.state.nav
|
||||
@@ -257,6 +265,16 @@ export default function createNavigationContainer(Component) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.tron &&
|
||||
console.tron.display({
|
||||
name: 'Navigation',
|
||||
preview: 'Initial State',
|
||||
value: {
|
||||
initialState: startupState,
|
||||
initialAction: this._initialAction,
|
||||
},
|
||||
});
|
||||
|
||||
this.setState({ nav: startupState }, () => {
|
||||
_reactNavigationIsHydratingState = false;
|
||||
dispatchActions();
|
||||
|
||||
@@ -397,7 +397,15 @@ export default (routeConfigs, stackConfig = {}) => {
|
||||
|
||||
// Handle replace action
|
||||
if (action.type === StackActions.REPLACE) {
|
||||
const routeIndex = state.routes.findIndex(r => r.key === action.key);
|
||||
let routeIndex;
|
||||
|
||||
// If the key param is undefined, set the index to the last route in the stack
|
||||
if (action.key === undefined && state.routes.length) {
|
||||
routeIndex = state.routes.length - 1;
|
||||
} else {
|
||||
routeIndex = state.routes.findIndex(r => r.key === action.key);
|
||||
}
|
||||
|
||||
// Only replace if the key matches one of our routes
|
||||
if (routeIndex !== -1) {
|
||||
const childRouter = childRouters[action.routeName];
|
||||
|
||||
@@ -970,6 +970,77 @@ describe('StackRouter', () => {
|
||||
expect(replacedState2.routes[0].routeName).toEqual('bar');
|
||||
});
|
||||
|
||||
test('Replace action returns most recent route if no key is provided', () => {
|
||||
const GrandChildNavigator = () => <div />;
|
||||
GrandChildNavigator.router = StackRouter({
|
||||
Quux: { screen: () => <div /> },
|
||||
Corge: { screen: () => <div /> },
|
||||
Grault: { screen: () => <div /> },
|
||||
});
|
||||
|
||||
const ChildNavigator = () => <div />;
|
||||
ChildNavigator.router = StackRouter({
|
||||
Baz: { screen: () => <div /> },
|
||||
Woo: { screen: () => <div /> },
|
||||
Qux: { screen: GrandChildNavigator },
|
||||
});
|
||||
|
||||
const router = StackRouter({
|
||||
Foo: { screen: () => <div /> },
|
||||
Bar: { screen: ChildNavigator },
|
||||
});
|
||||
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
const state2 = router.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'Bar',
|
||||
},
|
||||
state
|
||||
);
|
||||
const state3 = router.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'Qux',
|
||||
},
|
||||
state2
|
||||
);
|
||||
const state4 = router.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'Corge',
|
||||
},
|
||||
state3
|
||||
);
|
||||
const state5 = router.getStateForAction(
|
||||
{
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'Grault',
|
||||
},
|
||||
state4
|
||||
);
|
||||
|
||||
const replacedState = router.getStateForAction(
|
||||
StackActions.replace({
|
||||
routeName: 'Woo',
|
||||
params: { meaning: 42 },
|
||||
}),
|
||||
state5
|
||||
);
|
||||
|
||||
const originalCurrentScreen = state5.routes[1].routes[1].routes[2];
|
||||
const replacedCurrentScreen = replacedState.routes[1].routes[1].routes[2];
|
||||
|
||||
expect(replacedState.routes[1].routes[1].index).toEqual(2);
|
||||
expect(replacedState.routes[1].routes[1].routes.length).toEqual(3);
|
||||
expect(replacedCurrentScreen.key).not.toEqual(originalCurrentScreen.key);
|
||||
expect(replacedCurrentScreen.routeName).not.toEqual(
|
||||
originalCurrentScreen.routeName
|
||||
);
|
||||
expect(replacedCurrentScreen.routeName).toEqual('Woo');
|
||||
expect(replacedCurrentScreen.params.meaning).toEqual(42);
|
||||
});
|
||||
|
||||
test('Handles push transition logic with completion action', () => {
|
||||
const FooScreen = () => <div />;
|
||||
const BarScreen = () => <div />;
|
||||
|
||||
Reference in New Issue
Block a user