mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-12 22:51:18 +08:00
feat: add native container with back button integration (#48)
This commit is contained in:
committed by
Satyajit Sahoo
parent
4a3db4e6f4
commit
b7735af7fc
@@ -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",
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -243,9 +243,9 @@ export default function useNavigationBuilder<
|
||||
setState,
|
||||
onRouteFocus,
|
||||
addActionListener,
|
||||
addFocusedListener,
|
||||
router,
|
||||
emitter,
|
||||
addFocusedListener,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -39,6 +39,7 @@ module.exports = {
|
||||
'react-native-paper',
|
||||
'react-native-tab-view',
|
||||
'shortid',
|
||||
'use-subscription',
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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))
|
||||
|
||||
19
packages/native/package.json
Normal file
19
packages/native/package.json
Normal 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": "*"
|
||||
}
|
||||
}
|
||||
2
packages/native/src/index.tsx
Normal file
2
packages/native/src/index.tsx
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as useBackButton } from './useBackButton';
|
||||
export { default as useNativeIntegration } from './useNativeIntegration';
|
||||
30
packages/native/src/useBackButton.tsx
Normal file
30
packages/native/src/useBackButton.tsx
Normal 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]);
|
||||
}
|
||||
9
packages/native/src/useNativeIntegration.tsx
Normal file
9
packages/native/src/useNativeIntegration.tsx
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user