feat: expose getActionForState in linking

This commit is contained in:
Satyajit Sahoo
2020-12-13 03:06:42 +01:00
parent 3c874191ff
commit c9a5d45324
3 changed files with 29 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
import type {
getStateFromPath as getStateFromPathDefault,
getPathFromState as getPathFromStateDefault,
getActionFromState as getActionFromStateDefault,
PathConfigMap,
Route,
} from '@react-navigation/core';
@@ -90,11 +91,18 @@ export type LinkingOptions = {
) => undefined | void | (() => void);
/**
* Custom function to parse the URL to a valid navigation state (advanced).
* This state object will be passed as `initialState` for initial URL,
* and converted to an action object to `dispatch` for subsequent URLs.
*/
getStateFromPath?: typeof getStateFromPathDefault;
/**
* Custom function to convert the state object to an action to dispatch (advanced).
* By default, the state is converted to a `NAVIGATE` action.
*/
getActionFromState?: typeof getActionFromStateDefault;
/**
* Custom function to convert the state object to a valid URL (advanced).
* Only applicable on Web.
* Used for creating links for navigation, primarily useful on Web.
*/
getPathFromState?: typeof getPathFromStateDefault;
};

View File

@@ -1,12 +1,12 @@
import * as React from 'react';
import { Linking, Platform } from 'react-native';
import {
getActionFromState,
getActionFromState as getActionFromStateDefault,
getStateFromPath as getStateFromPathDefault,
NavigationContainerRef,
} from '@react-navigation/core';
import type { LinkingOptions } from './types';
import escapeStringRegexp from 'escape-string-regexp';
import type { LinkingOptions } from './types';
let isUsingLinking = false;
@@ -33,6 +33,7 @@ export default function useLinking(
return () => Linking.removeEventListener('url', callback);
},
getStateFromPath = getStateFromPathDefault,
getActionFromState = getActionFromStateDefault,
}: LinkingOptions
) {
React.useEffect(() => {
@@ -66,6 +67,7 @@ export default function useLinking(
const configRef = React.useRef(config);
const getInitialURLRef = React.useRef(getInitialURL);
const getStateFromPathRef = React.useRef(getStateFromPath);
const getActionFromStateRef = React.useRef(getActionFromState);
React.useEffect(() => {
enabledRef.current = enabled;
@@ -73,7 +75,8 @@ export default function useLinking(
configRef.current = config;
getInitialURLRef.current = getInitialURL;
getStateFromPathRef.current = getStateFromPath;
}, [config, enabled, prefixes, getInitialURL, getStateFromPath]);
getActionFromStateRef.current = getActionFromState;
});
const extractPathFromURL = React.useCallback((url: string) => {
for (const prefix of prefixesRef.current) {
@@ -134,7 +137,10 @@ export default function useLinking(
return;
}
const action = getActionFromState(state, configRef.current);
const action = getActionFromStateRef.current(
state,
configRef.current
);
if (action !== undefined) {
try {

View File

@@ -2,9 +2,9 @@ import * as React from 'react';
import {
getStateFromPath as getStateFromPathDefault,
getPathFromState as getPathFromStateDefault,
getActionFromState as getActionFromStateDefault,
NavigationContainerRef,
NavigationState,
getActionFromState,
} from '@react-navigation/core';
import { nanoid } from 'nanoid/non-secure';
import ServerContext from './ServerContext';
@@ -134,7 +134,7 @@ const createMemoryHistory = () => {
// - There's history to go back, `history.go` is called, and `popstate` fires
// - `history.go` is called multiple times, we need to resolve on respective `popstate`
// - No history to go back, but `history.go` was called, browser has no API to detect it
return new Promise((resolve, reject) => {
return new Promise<void>((resolve, reject) => {
const done = (interrupted?: boolean) => {
clearTimeout(timer);
@@ -293,6 +293,7 @@ export default function useLinking(
config,
getStateFromPath = getStateFromPathDefault,
getPathFromState = getPathFromStateDefault,
getActionFromState = getActionFromStateDefault,
}: LinkingOptions
) {
React.useEffect(() => {
@@ -323,14 +324,16 @@ export default function useLinking(
const enabledRef = React.useRef(enabled);
const configRef = React.useRef(config);
const getStateFromPathRef = React.useRef(getStateFromPath);
const getActionFromStateRef = React.useRef(getActionFromState);
const getPathFromStateRef = React.useRef(getPathFromState);
React.useEffect(() => {
enabledRef.current = enabled;
configRef.current = config;
getStateFromPathRef.current = getStateFromPath;
getActionFromStateRef.current = getActionFromState;
getPathFromStateRef.current = getPathFromState;
}, [config, enabled, getPathFromState, getStateFromPath]);
});
const server = React.useContext(ServerContext);
@@ -412,7 +415,10 @@ export default function useLinking(
}
if (index > previousIndex) {
const action = getActionFromState(state, configRef.current);
const action = getActionFromStateRef.current(
state,
configRef.current
);
if (action !== undefined) {
try {