feat: add native container with back button integration (#48)

This commit is contained in:
Michał Osadnik
2019-08-14 15:04:21 +01:00
committed by Satyajit Sahoo
parent 4a3db4e6f4
commit b7735af7fc
12 changed files with 94 additions and 7 deletions

View File

@@ -4,6 +4,7 @@
"react": { "version": "16" },
"import/core-modules": [
"@navigation-ex/core",
"@navigation-ex/native",
"@navigation-ex/routers",
"@navigation-ex/stack",
"@navigation-ex/drawer",

View File

@@ -99,8 +99,19 @@ const Container = React.forwardRef(function NavigationContainer(
listeners[0](navigation => navigation.dispatch(action));
};
const canGoBack = () => {
const { result, handled } = listeners[0](navigation =>
navigation.canGoBack()
);
if (handled) {
return result;
} else {
return false;
}
};
React.useImperativeHandle(ref, () => ({
dispatch,
...(Object.keys(BaseActions) as Array<keyof typeof BaseActions>).reduce<
any
>((acc, name) => {
@@ -114,6 +125,8 @@ const Container = React.forwardRef(function NavigationContainer(
);
return acc;
}, {}),
dispatch,
canGoBack,
}));
const navigationStateRef = React.useRef<State>();

View File

@@ -55,12 +55,13 @@ export default function useDescriptors<
getState,
setState,
addActionListener,
addFocusedListener,
onRouteFocus,
router,
emitter,
addFocusedListener,
}: Options<ScreenOptions>) {
const [options, setOptions] = React.useState<{ [key: string]: object }>({});
const context = React.useMemo(
() => ({
navigation,

View File

@@ -243,9 +243,9 @@ export default function useNavigationBuilder<
setState,
onRouteFocus,
addActionListener,
addFocusedListener,
router,
emitter,
addFocusedListener,
});
return {

View File

@@ -35,7 +35,7 @@ export default function useNavigationHelpers<
const { performTransaction } = React.useContext(NavigationStateContext);
return React.useMemo(() => {
const dispatch = (action: Action | ((state: State) => State)) => {
const dispatch = (action: Action | ((state: State) => State)) =>
performTransaction(() => {
if (typeof action === 'function') {
setState(action(getState()));
@@ -43,7 +43,6 @@ export default function useNavigationHelpers<
onAction(action);
}
});
};
const actions = {
...router.actionCreators,

View File

@@ -39,6 +39,7 @@ module.exports = {
'react-native-paper',
'react-native-tab-view',
'shortid',
'use-subscription',
],
},

View File

@@ -31,7 +31,8 @@
"react-native-tab-view": "2.7.1",
"react-native-web": "^0.11.4",
"scheduler": "^0.14.0",
"shortid": "^2.2.14"
"shortid": "^2.2.14",
"use-subscription": "^1.0.0"
},
"devDependencies": {
"@babel/core": "^7.5.5",

View File

@@ -2,7 +2,13 @@ import * as React from 'react';
import { ScrollView, AsyncStorage, YellowBox } from 'react-native';
import { Appbar, List } from 'react-native-paper';
import { Asset } from 'expo-asset';
import { NavigationContainer, InitialState } from '@navigation-ex/core';
import {
NavigationContainer,
InitialState,
NavigationHelpers,
ParamListBase,
} from '@navigation-ex/core';
import { useNativeIntegration } from '@navigation-ex/native';
import {
createDrawerNavigator,
DrawerNavigationProp,
@@ -51,6 +57,10 @@ const PERSISTENCE_KEY = 'NAVIGATION_STATE';
Asset.loadAsync(StackAssets);
export default function App() {
const containerRef = React.useRef<NavigationHelpers<ParamListBase>>(null);
useNativeIntegration(containerRef);
const [isReady, setIsReady] = React.useState(false);
const [initialState, setInitialState] = React.useState<
InitialState | undefined
@@ -79,6 +89,7 @@ export default function App() {
return (
<NavigationContainer
ref={containerRef}
initialState={initialState}
onStateChange={state =>
AsyncStorage.setItem(PERSISTENCE_KEY, JSON.stringify(state))

View File

@@ -0,0 +1,19 @@
{
"name": "@navigation-ex/native",
"version": "0.0.1",
"main": "src/index",
"license": "MIT",
"dependencies": {
"@navigation-ex/core": "^0.0.1"
},
"devDependencies": {
"@types/react": "^16.8.24",
"@types/react-native": "^0.60.2",
"react": "16.8.3",
"react-native": "^0.59.8"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
}

View File

@@ -0,0 +1,2 @@
export { default as useBackButton } from './useBackButton';
export { default as useNativeIntegration } from './useNativeIntegration';

View File

@@ -0,0 +1,30 @@
import * as React from 'react';
import { NavigationHelpers, ParamListBase } from '@navigation-ex/core';
import { BackHandler } from 'react-native';
export default function useBackButton(
ref: React.RefObject<NavigationHelpers<ParamListBase>>
) {
React.useEffect(() => {
const subscription = BackHandler.addEventListener(
'hardwareBackPress',
() => {
if (ref.current == null) {
return false;
}
const navigation = ref.current;
if (navigation.canGoBack()) {
navigation.goBack();
return true;
}
return false;
}
);
return () => subscription.remove();
}, [ref]);
}

View File

@@ -0,0 +1,9 @@
import * as React from 'react';
import { NavigationHelpers, ParamListBase } from '@navigation-ex/core';
import useBackButton from './useBackButton';
export default function useNativeIntegration(
ref: React.RefObject<NavigationHelpers<ParamListBase>>
) {
useBackButton(ref);
}