-
Notifications
You must be signed in to change notification settings - Fork 36
Refine use navigation param #20
Refine use navigation param #20
Conversation
Very neat! I'm not particularly well-versed in typescript either, so you probably tried this, but I would expect Though, digging a bit to see what the type of Honestly, I wouldn't worry too much about the fallback value param--it does make sense I think to support it, since it matches what Thanks a lot for writing up this PR btw! 😄 |
src/Hooks.ts
Outdated
const { getParam, setParams } = useNavigation() | ||
return [ | ||
getParam(paramName, fallbackValue), | ||
(newValue: NonNullable<NavigationParams[T]>) => setParams({ [paramName]: newValue }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe worth wrapping this in React.useCallback
to preserve the reference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which part exactly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function which is used to update the param
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if it's that much of a performance difference to just memoize the reference to that function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not about performance optimisation due to memoizing, but it will avoid extra step to memoize it if you are using React.memo
or React.PureComponent
. iirc, the updater function from React.useState
preserves the reference for this reason
@satya164 Thank you for the review! I pushed some changes, that resolve most of the change requests and the failing linter :) |
src/Hooks.ts
Outdated
const { getParam, setParams } = useNavigation() | ||
return [ | ||
fallbackValue ? getParam(paramName, fallbackValue) : getParam(paramName), | ||
(newValue: NavigationParams[T]) => setParams({ [paramName]: newValue }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with @satya164, need useCallback here
const setParamValue = useCallback(() => {
return (newValue: NavigationParams[T]) => setParams({ [paramName]: newValue });
},[setParams]);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay - I just implemented it like you suggested :)
Thanks @benseitz , that looks fine to me Can you rebase and resolve the conflicts? I'm not going to merge it very soon because it's a breaking chance, will try to see what other breaking changes we can do for a v2 |
@slorber we are not, in v5 the For handling optional params and default value, the upcoming optional chaining and nullish coalescing operators work well: - useNavigation().getParam('foo, 'defaultValue')
+ useRoute().params?.foo ?? 'defaultValue' We do have a |
so, @satya164 do you think we should merge it? I think it's not a big deal even if v5 does not have it, because we already have useNavigationParam() anyway. The other option would be to remove it and ask user to use optional chaining, but not sure many have enabled it on their babel setup (TS just merged the PR) |
Regarding optional chaining, React Navigation v5 is still in alpha, so I'm not much worried about it not being available by default yet. Regarding whether to merge the PR, it's upto you. Though a breaking change for this when upgrading to hooks v2 and again when upgrading to navigation v5 might not be best. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your work 👍 Added fix for "Maximum update depth exceeded" crash and left suggestion to make Typescript users' life better :)
export function useNavigationParam<T extends keyof NavigationParams>( | ||
paramName: T | ||
paramName: T, | ||
fallbackValue?: NavigationParams[T] | ||
) { | ||
return useNavigation().getParam(paramName); | ||
const { getParam, setParams } = useNavigation(); | ||
const setParamValue = useCallback( | ||
() => { | ||
return (newValue: NavigationParams[T]) => | ||
setParams({ [paramName]: newValue }); | ||
}, | ||
[setParams] | ||
); | ||
return [ | ||
fallbackValue ? getParam(paramName, fallbackValue) : getParam(paramName), | ||
setParamValue(), | ||
]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export default function useNavigationParam<
T extends keyof Params,
Params extends NavigationParams = NavigationParams
>(
paramName: T,
fallback?: Params[T],
): [Params[T], (value: Params[T]) => boolean] {
const { getParam, setParams } = useNavigation();
const setParamValue = useCallback(
(newValue: Params[T]) => setParams({ [paramName]: newValue }),
// `setParams` function is not memoized, so that it causes "Maximum update depth exceeded" (https://github.com/react-navigation/core/issues/71)
// eslint-disable-next-line react-hooks/exhaustive-deps
[paramName],
);
// had to cast `paramName` because `navigation.getParam` thinks that some other type can be passed
return [getParam(paramName as string, fallback), setParamValue];
}
I would suggest these change where I added additional optional type Params
for NavigationParams
, so that you can optionally determine actual types of keys' values instead of seeing any
(it is made possible with Index types
http://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types). There is case when type is misleading, fallback
value will always be shown as possibly undefined even if it is required in Params
.
Also fixed "Maximum update depth exceeded" which described in suggestion below and added paramName
to deps as ESlint
suggested
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix "Maximum update depth exceeded" crash in current implementation
const setParamValue = useCallback( | ||
() => { | ||
return (newValue: NavigationParams[T]) => | ||
setParams({ [paramName]: newValue }); | ||
}, | ||
[setParams] | ||
); | ||
return [ | ||
fallbackValue ? getParam(paramName, fallbackValue) : getParam(paramName), | ||
setParamValue(), | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both setParams
in deps of useCallback
(https://github.com/react-navigation/core/issues/71) and redundant function wrapping causes crash with "Maximum update depth exceeded" error in my React-Native app, so suggest to avoid it. Also added paramName
prop as ESLint
suggested
const setParamValue = useCallback(
(newValue: NavigationParams[T]) => setParams({ [paramName]: newValue }),
// `setParams` function is not memoized, so that it causes "Maximum update depth exceeded" (https://github.com/react-navigation/core/issues/71)
// eslint-disable-next-line react-hooks/exhaustive-deps
[paramName],
);
return [
fallbackValue ? getParam(paramName, fallbackValue) : getParam(paramName),
setParamValue,
];
Hi, I think we'd better not ship this feature if this is not in v5 Thanks |
Introduces a
useState
like API foruseNavigationParam
as suggested in #19 and allows a fallback value as a second argument.Theres also an updated and one added test as well as updated documentation and a new warning because of this breaking changes.
Currently the linter is failing because of a missing type for
fallbackValue
.Since I'm not very fluent in typescript I'd couldn't find a solution that doesn't end in errors :/