Compare commits

..

6 Commits
2.2.3 ... 2.2.5

Author SHA1 Message Date
Brent Vatne
992d0fb267 Release 2.2.5 2018-06-08 09:40:39 -07:00
ensecoz
6f41379ed1 extract correct property for onTransitionEnd (#4459) 2018-06-08 09:35:36 -07:00
Tom Klaver
267af01e72 throw readable error when wrong navigation prop is passed (#4455)
* add warning when passing wrong navigation prop: https://github.com/react-navigation/react-navigation/issues/3598

* add test for throwing when passing wrong navigation prop

* wrong nav prop error: update snapshots, throw => throw new, update docs reference url
2018-06-08 09:31:05 -07:00
Arthur Levoyer
b68c3a755d Add missing tests about DeepLinking (#4451)
* Fix #1950 (Deep link not working when nesting have more than two levels.)

* Fix test
2018-06-07 11:37:57 -07:00
Brent Vatne
7345634493 Release 2.2.4 2018-06-07 11:33:14 -07:00
Brent Vatne
6517169119 Re-compute options when screenProps change 2018-06-07 11:31:31 -07:00
6 changed files with 458 additions and 7 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "react-navigation",
"version": "2.2.3",
"version": "2.2.5",
"description": "Routing and navigation for your React Native apps",
"main": "src/react-navigation.js",
"repository": {

View File

@@ -0,0 +1,40 @@
import React from 'react';
import renderer from 'react-test-renderer';
import StackNavigator from '../createStackNavigator';
const SubNavigator = StackNavigator({
Home: {
screen: () => null,
},
});
const NavNestedDirect = StackNavigator({
Sub: {
screen: SubNavigator,
},
});
const NavNestedIndirect = StackNavigator({
Sub: {
// eslint-disable-next-line react/display-name
screen: props => <SubNavigator {...props} />,
},
});
/* Prevent React error boundaries from swallowing the errors */
NavNestedIndirect.prototype.componentDidCatch = null;
SubNavigator.prototype.componentDidCatch = null;
describe('Nested navigators', () => {
it('renders succesfully as direct child', () => {
const rendered = renderer.create(<NavNestedDirect />).toJSON();
expect(rendered).toMatchSnapshot();
});
it('throw when trying to pass navigation prop', () => {
const tryRender = () => {
renderer.create(<NavNestedIndirect />);
};
expect(tryRender).toThrowErrorMatchingSnapshot();
});
});

View File

@@ -0,0 +1,359 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Nested navigators renders succesfully as direct child 1`] = `
<View
onLayout={[Function]}
style={
Array [
Object {
"flex": 1,
},
]
}
>
<View
onMoveShouldSetResponder={[Function]}
onMoveShouldSetResponderCapture={[Function]}
onResponderEnd={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderReject={[Function]}
onResponderRelease={[Function]}
onResponderStart={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
onStartShouldSetResponderCapture={[Function]}
style={
Array [
Object {
"flex": 1,
"flexDirection": "column-reverse",
},
Object {
"backgroundColor": "#000",
},
]
}
>
<View
style={
Object {
"flex": 1,
}
}
>
<View
collapsable={undefined}
pointerEvents="auto"
style={
Object {
"backgroundColor": "#E9E9EF",
"bottom": 0,
"left": 0,
"marginTop": 0,
"opacity": 1,
"position": "absolute",
"right": 0,
"shadowColor": "black",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.2,
"shadowRadius": 5,
"top": 0,
"transform": Array [
Object {
"translateX": 0,
},
Object {
"translateY": 0,
},
],
}
}
>
<View
onLayout={[Function]}
style={
Array [
Object {
"flex": 1,
},
]
}
>
<View
onMoveShouldSetResponder={[Function]}
onMoveShouldSetResponderCapture={[Function]}
onResponderEnd={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderReject={[Function]}
onResponderRelease={[Function]}
onResponderStart={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
onStartShouldSetResponderCapture={[Function]}
style={
Array [
Object {
"flex": 1,
"flexDirection": "column-reverse",
},
Object {
"backgroundColor": "#000",
},
]
}
>
<View
style={
Object {
"flex": 1,
}
}
>
<View
collapsable={undefined}
pointerEvents="auto"
style={
Object {
"backgroundColor": "#E9E9EF",
"bottom": 0,
"left": 0,
"marginTop": 0,
"opacity": 1,
"position": "absolute",
"right": 0,
"shadowColor": "black",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.2,
"shadowRadius": 5,
"top": 0,
"transform": Array [
Object {
"translateX": 0,
},
Object {
"translateY": 0,
},
],
}
}
/>
</View>
<View
collapsable={undefined}
style={
Object {
"transform": Array [
Object {
"translateX": 0,
},
],
}
}
>
<View
collapsable={undefined}
onLayout={[Function]}
pointerEvents="box-none"
style={
Object {
"backgroundColor": "#F7F7F7",
"borderBottomColor": "#A7A7AA",
"borderBottomWidth": 0.5,
"height": 64,
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 20,
}
}
>
<View
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
/>
<View
style={
Object {
"flex": 1,
}
}
>
<View
style={
Object {
"bottom": 0,
"flexDirection": "row",
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<View
collapsable={undefined}
pointerEvents="box-none"
style={
Object {
"alignItems": "center",
"backgroundColor": "transparent",
"bottom": 0,
"flexDirection": "row",
"justifyContent": "center",
"left": 0,
"opacity": 1,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<Text
accessibilityTraits="header"
accessible={true}
allowFontScaling={true}
collapsable={undefined}
ellipsizeMode="tail"
numberOfLines={1}
onLayout={[Function]}
style={
Object {
"color": "rgba(0, 0, 0, .9)",
"fontSize": 17,
"fontWeight": "700",
"marginHorizontal": 16,
"textAlign": "center",
}
}
/>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
<View
collapsable={undefined}
style={
Object {
"transform": Array [
Object {
"translateX": 0,
},
],
}
}
>
<View
collapsable={undefined}
onLayout={[Function]}
pointerEvents="box-none"
style={
Object {
"backgroundColor": "#F7F7F7",
"borderBottomColor": "#A7A7AA",
"borderBottomWidth": 0.5,
"height": 64,
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 20,
}
}
>
<View
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
/>
<View
style={
Object {
"flex": 1,
}
}
>
<View
style={
Object {
"bottom": 0,
"flexDirection": "row",
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<View
collapsable={undefined}
pointerEvents="box-none"
style={
Object {
"alignItems": "center",
"backgroundColor": "transparent",
"bottom": 0,
"flexDirection": "row",
"justifyContent": "center",
"left": 0,
"opacity": 1,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<Text
accessibilityTraits="header"
accessible={true}
allowFontScaling={true}
collapsable={undefined}
ellipsizeMode="tail"
numberOfLines={1}
onLayout={[Function]}
style={
Object {
"color": "rgba(0, 0, 0, .9)",
"fontSize": 17,
"fontWeight": "700",
"marginHorizontal": 16,
"textAlign": "center",
}
}
/>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
`;
exports[`Nested navigators throw when trying to pass navigation prop 1`] = `"No \\"routes\\" found in navigation state. Did you try to pass the navigation prop of a React component to a Navigator child? See https://reactnavigation.org/docs/en/custom-navigators.html#navigator-navigation-prop"`;

View File

@@ -8,20 +8,35 @@ function createNavigator(NavigatorView, router, navigationConfig) {
static router = router;
static navigationOptions = null;
state = {
descriptors: {},
childEventSubscribers: {},
};
constructor(props) {
super(props);
this.state = {
descriptors: {},
childEventSubscribers: {},
screenProps: props.screenProps,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
const { navigation, screenProps } = nextProps;
const { dispatch, state, addListener } = navigation;
const { routes } = state;
if (typeof routes === 'undefined') {
throw new TypeError(
'No "routes" found in navigation state. Did you try to pass the navigation prop of a React component to a Navigator child? See https://reactnavigation.org/docs/en/custom-navigators.html#navigator-navigation-prop'
);
}
const descriptors = { ...prevState.descriptors };
const childEventSubscribers = { ...prevState.childEventSubscribers };
routes.forEach(route => {
if (!descriptors[route.key] || descriptors[route.key].state !== route) {
if (
!descriptors[route.key] ||
descriptors[route.key].state !== route ||
screenProps !== prevState.screenProps
) {
const getComponent = () =>
router.getComponentForRouteName(route.routeName);
@@ -75,6 +90,7 @@ function createNavigator(NavigatorView, router, navigationConfig) {
return {
descriptors,
childEventSubscribers,
screenProps,
};
}

View File

@@ -426,12 +426,47 @@ describe('StackRouter', () => {
expect(state3 && state3.index).toEqual(0);
});
test('Handle navigation to nested navigator', () => {
const state = TestStackRouter.getStateForAction({
type: NavigationActions.INIT,
});
const action = TestStackRouter.getActionForPathAndParams('fo/22/b/hello');
/* $FlowFixMe */
const state2 = TestStackRouter.getStateForAction(action);
expect(state2).toEqual({
index: 0,
isTransitioning: false,
key: 'StackRouterRoot',
routes: [
{
index: 0,
key: 'id-4',
isTransitioning: false,
routeName: 'foo',
params: {
fooThing: '22',
},
routes: [
{
routeName: 'bar',
key: 'id-3',
params: {
barThing: 'hello',
},
},
],
},
],
});
});
test('popToTop bubbles up', () => {
const ChildNavigator = () => <div />;
ChildNavigator.router = StackRouter({
Baz: { screen: () => <div /> },
Qux: { screen: () => <div /> },
});
const router = StackRouter({
Foo: { screen: () => <div /> },
Bar: { screen: ChildNavigator },

View File

@@ -26,7 +26,8 @@ class StackView extends React.Component {
descriptors={this.props.descriptors}
onTransitionStart={this.props.onTransitionStart}
onTransitionEnd={(transition, lastTransition) => {
const { onTransitionEnd, navigation } = this.props;
const { navigationConfig, navigation } = this.props;
const { onTransitionEnd } = navigationConfig;
if (transition.navigation.state.isTransitioning) {
navigation.dispatch(
StackActions.completeTransition({