Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow preload using activityState #2389

Merged
merged 7 commits into from
Oct 10, 2024

Conversation

maciekstosio
Copy link
Contributor

@maciekstosio maciekstosio commented Oct 4, 2024

Description

This PR is a rewrite of #2278 using already existing activityState -> to avoid introducing redundant prop.

Connected PR to react-navigation: react-navigation/react-navigation#12189

Test code and steps to reproduce

You can play with the preload feature in TestPreload.tsx

To test assertion of activityState progress go to TestActivityStateProgression.tsx - keep in mind that if the Screen has isNativeStack it will just run JS validation, remove the prop to test native checks.

Checklist

kkafar added a commit to react-navigation/react-navigation that referenced this pull request Oct 8, 2024
Preload feature implemented in
#12083, with
the difference of renaming prop `shouldBePreloaded` into `isPreloaded`
and reusing `activityState` instead of new `hiddenFromStack`. Matching
PR in react-native-screens repo:
software-mansion/react-native-screens#2389

---------

Co-authored-by: Maksymilian Galas <maksymilian.galas@swmansion.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Kacper Kafara <kacperkafara@gmail.com>
@kkafar kkafar marked this pull request as ready for review October 9, 2024 12:07
@kkafar kkafar mentioned this pull request Oct 9, 2024
8 tasks
Copy link
Member

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job!

@@ -165,6 +166,7 @@ export const InnerScreen = React.forwardRef<View, ScreenProps>(
function InnerScreen(props, ref) {
const innerRef = React.useRef<ViewConfig | null>(null);
React.useImperativeHandle(ref, () => innerRef.current!, []);
const prevActivityState = usePrevious(props.activityState);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like running another useEffect every render, however this should be ok for now, since we want to relax this constraint in future.

@kkafar kkafar merged commit cce7d78 into main Oct 10, 2024
8 checks passed
@kkafar kkafar deleted the @maciekstosio/Preload-feature-using-activityState- branch October 10, 2024 09:46
kkafar added a commit that referenced this pull request Oct 15, 2024
## Description

We had an issue introduced in #2389 that added the preload. We
temporarily
have an assumption in native stack, that the `activityState` can only
progress when
`Screen` component is rendered (directly) inside native stack navigator.
This invariant
was enforced with appropriate checks on native side. It turns out that
we were wrong in our
way of checking whether the `Screen` belongs to native stack or not - we
have forgotten about
`RNSContainerNavigationController` class that is used when rendering
`ScreenContainer` with `hasTwoStates: true`
and which inherits from `RNSNavigationController`.

## Changes

~Added a `isNativeStackViewController` method to
`RNSNavigationController` and overrode it in subclass.~

Added `RNSScreenView#isNativeStackScreen` method, which checks whether
our direct react superview is a `RNSScreenStackView`.

I've found checking for `_controller.navigationController` not reliable,
as `navigationController` can be found arbitrarily high in the view
hierarchy.

## Test code and steps to reproduce

Reported by Expo. If you want to reproduce this: create a JS stack
navigator with bottom tabs inside (with `hasTwoStates: true`),
and then a regular JS stack inside & try to navigate to any screen. 

We have not caught that earlier, because we're not testing regular JS
stack at all.

## Checklist

- [ ] Included code example that can be used to test this change
- [x] Ensured that CI passes
kkafar added a commit that referenced this pull request Oct 15, 2024
## Description

We did not set default value of `activityState` on iOS. It was set to
`0` by default `int` initializer.

In `Screen` component native spec we set it to `-1`, however this had no
impact, because the value setter
`setActivityStateOrNil:` filtered out the `-1` value.

TODO:

1. [x] Verify that change in default value do not break any other
navigator!

^ Looks like this will work, because navigators such as bottom tabs
always set the activity state explicitly.


This is a problem, because now, after adding preload support #2389 we
filter out screens with `activityState == 0` in native stack.
Therefore, we now unintentionally force our API user to always set
desired `activityState`.

## Changes

Set `activityState` to `-1` by default on native side.

## Test code and steps to reproduce

Just render screen inside native-stack w/o `activityState` set. It won't
be shown.
 
## Checklist

- [ ] Included code example that can be used to test this change
- [ ] Ensured that CI passes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants