-
Notifications
You must be signed in to change notification settings - Fork 35
useFocusEffect / useIsFocused #43
Changes from all commits
3304438
21d754e
ab60ff2
18ced88
049a46c
88b61a7
5044bca
d354567
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import { | ||
useState, | ||
useContext, | ||
useEffect, | ||
useLayoutEffect, | ||
useRef, | ||
useCallback, | ||
|
@@ -143,3 +144,67 @@ export function useFocusState() { | |
|
||
return focusState; | ||
} | ||
|
||
type EffectCallback = (() => void) | (() => () => void); | ||
|
||
// Inspired by same hook from react-navigation v5 | ||
// See https://github.com/react-navigation/hooks/issues/39#issuecomment-534694135 | ||
export const useFocusEffect = (callback: EffectCallback) => { | ||
const navigation = useNavigation(); | ||
|
||
useEffect(() => { | ||
let isFocused = false; | ||
let cleanup: (() => void) | void; | ||
|
||
if (navigation.isFocused()) { | ||
cleanup = callback(); | ||
isFocused = true; | ||
} | ||
|
||
const focusSubscription = navigation.addListener('willFocus', () => { | ||
// If callback was already called for focus, avoid calling it again | ||
// The focus event may also fire on intial render, so we guard against runing the effect twice | ||
if (isFocused) { | ||
return; | ||
} | ||
|
||
cleanup && cleanup(); | ||
cleanup = callback(); | ||
isFocused = true; | ||
}); | ||
|
||
const blurSubscription = navigation.addListener('willBlur', () => { | ||
cleanup && cleanup(); | ||
cleanup = undefined; | ||
isFocused = false; | ||
}); | ||
|
||
return () => { | ||
cleanup && cleanup(); | ||
focusSubscription.remove(); | ||
blurSubscription.remove(); | ||
}; | ||
}, [callback, navigation]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @slorber If I run setParams in callback, navigation will change and invoke callback again, it will raise a infinite loop There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for reporting this. @satya164 how do you handle those loops in v5? I guess we should fix it the same way in v5 and here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. v5 doesn't update There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @satya164 I understand your point about preventing useless re-renders/infinite loops. But if param value has to change, we still don't necessarily want to re-execute useFocusEffect again (at least user should be in control imho) I mean: This one should re-execute on userId param change useFocusEffect(useCallback(() => { ... },[params.userId])); But this one should rather not re-execute even if any param changes: useFocusEffect(useCallback(() => { ... },[])); So I think it's not correct to make this hook depend on navigation here, as the object is unstable it will tend to produce unwanted effect re-execution. I guess it will even re-execute if the parent re-renders for example. I've opened another issue: #48 |
||
}; | ||
|
||
export const useIsFocused = () => { | ||
const navigation = useNavigation(); | ||
const getNavigation = useGetter(navigation); | ||
const [focused, setFocused] = useState(navigation.isFocused); | ||
|
||
useEffect(() => { | ||
const nav = getNavigation(); | ||
const focusSubscription = nav.addListener('willFocus', () => | ||
setFocused(true) | ||
); | ||
const blurSubscription = nav.addListener('willBlur', () => | ||
setFocused(false) | ||
); | ||
return () => { | ||
focusSubscription.remove(); | ||
blurSubscription.remove(); | ||
}; | ||
}, [getNavigation]); | ||
|
||
return focused; | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.