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: add freezeOnBlur prop #10834

Merged
merged 8 commits into from
Sep 16, 2022
Merged

Conversation

kacperkapusciak
Copy link
Member

@kacperkapusciak kacperkapusciak commented Sep 12, 2022

Motivation

Since version v3.9.0 react-native-screens exposed enableFreeze() function which allows to suspend all hidden screens from rendering with the use of react-freeze library.

This PR adds a new prop called freezeOnBlur which makes it possible to decide per screen which screen should be suspended from rendering.

Test plan

This feature needs react-native-screens with version >=3.16 so as of today we're not able to test this prop within Expo Go.

Update screens to the newest version

yarn up react-native-screens

Run example in bare-workflow

yarn example ios
yarn example android

Use code samples below to test the feature

Only a visible screen should console.log in native-stack.
In stack, two top-most screens should console.log.

Code example for Stack and Native-Stack
import { NavigationContainer } from '@react-navigation/native';
// import { createStackNavigator } from '@react-navigation/stack';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import * as React from 'react';
import { Button, ScrollView, Text, View } from 'react-native';
// import { enableFreeze } from 'react-native-screens';

// enableFreeze();

const store = new Set<Dispatch>();

type Dispatch = (value: number) => void;

function useValue() {
  const [value, setValue] = React.useState<number>(0); // integer state

  React.useEffect(() => {
    const dispatch = (value: number) => {
      setValue(value);
    };
    store.add(dispatch);
    return () => store.delete(dispatch);
  }, [setValue]);

  return value;
}

function HomeScreen({ navigation }: any) {
  const value = useValue();
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen {value}</Text>
      <Button
        title="Go to Details"
        onPress={() => navigation.navigate('Details')}
      />
    </View>
  );
}

function DetailsScreen({ navigation }: any) {
  const value = useValue();
  // only 1 'render' should appear at the time
  console.log('render', value);
  return (
    <ScrollView>
      <View style={{ height: 400 }} />
      <Text style={{ alignSelf: 'center' }}>Details Screen {value}</Text>
      <Button
        title="Go to Details"
        onPress={() => navigation.push('Details')}
      />
      <View style={{ height: 800 }} />
    </ScrollView>
  );
}

const Stack = createNativeStackNavigator();
// const Stack = createStackNavigator();

function App() {
  React.useEffect(() => {
    let timer = 0;
    const interval = setInterval(() => {
      timer = timer + 1;
      store.forEach((dispatch) => dispatch(timer));
    }, 3000);
    return () => clearInterval(interval);
  }, []);

  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={{
          freezeOnBlur: true,
        }}
      >
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;

Only a visible screen should console.log

Code example for BottomTab and Drawer navigator
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
// import { createDrawerNavigator } from '@react-navigation/drawer';
import { NavigationContainer } from '@react-navigation/native';
import * as React from 'react';
import { Text, View } from 'react-native';

const store = new Set<Dispatch>();

type Dispatch = (value: number) => void;

function useValue() {
  const [value, setValue] = React.useState<number>(0); // integer state

  React.useEffect(() => {
    const dispatch = (value: number) => {
      setValue(value);
    };
    store.add(dispatch);
    return () => store.delete(dispatch);
  }, [setValue]);

  return value;
}

function HomeScreen() {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Home!</Text>
    </View>
  );
}

function DetailsScreen() {
  const value = useValue();
  // only 1 'render' should appear at the time
  console.log('render', value);
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Details!</Text>
      <Text style={{ alignSelf: 'center' }}>Details Screen {value}</Text>
    </View>
  );
}
const Tab = createBottomTabNavigator();
// const Tab = createDrawerNavigator();

export default function App() {
  React.useEffect(() => {
    let timer = 0;
    const interval = setInterval(() => {
      timer = timer + 1;
      store.forEach((dispatch) => dispatch(timer));
    }, 3000);
    return () => clearInterval(interval);
  }, []);

  return (
    <NavigationContainer>
      <Tab.Navigator screenOptions={{ freezeOnBlur: true }}>
        <Tab.Screen name="Home" component={HomeScreen} />
        <Tab.Screen name="Details" component={DetailsScreen} />
        <Tab.Screen name="Settings" component={DetailsScreen} />
        <Tab.Screen name="Profile" component={DetailsScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

Static

  • yarn lint
  • yarn typescript
  • yarn test
  • yarn lerna run prepack

@netlify
Copy link

netlify bot commented Sep 12, 2022

Deploy Preview for react-navigation-example ready!

Name Link
🔨 Latest commit 37402fa
🔍 Latest deploy log https://app.netlify.com/sites/react-navigation-example/deploys/6321c36a5d0c350008f45c84
😎 Deploy Preview https://deploy-preview-10834--react-navigation-example.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@github-actions
Copy link

The Expo app for the example from this branch is ready!

expo.dev/@react-navigation/react-navigation-example?release-channel=pr-10834

@codecov-commenter
Copy link

codecov-commenter commented Sep 14, 2022

Codecov Report

Merging #10834 (37402fa) into main (a6b7d10) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##             main   #10834   +/-   ##
=======================================
  Coverage   74.91%   74.91%           
=======================================
  Files         167      167           
  Lines        5130     5130           
  Branches     1986     1986           
=======================================
  Hits         3843     3843           
  Misses       1248     1248           
  Partials       39       39           
Impacted Files Coverage Δ
packages/bottom-tabs/src/views/BottomTabView.tsx 97.22% <ø> (ø)
packages/bottom-tabs/src/views/ScreenFallback.tsx 83.33% <ø> (ø)
packages/drawer/src/views/DrawerView.tsx 72.04% <ø> (ø)
packages/drawer/src/views/ScreenFallback.tsx 83.33% <ø> (ø)
.../native-stack/src/views/NativeStackView.native.tsx 69.09% <ø> (ø)
packages/stack/src/views/Screens.tsx 83.33% <ø> (ø)
packages/stack/src/views/Stack/CardStack.tsx 84.10% <ø> (ø)

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@kacperkapusciak kacperkapusciak marked this pull request as ready for review September 14, 2022 11:11
as these props will be added in the next screens version
@satya164 satya164 merged commit e13b4d9 into main Sep 16, 2022
@satya164 satya164 deleted the @kacperkapusciak/add-freezeOnBlur-prop branch September 16, 2022 13:33
@erksch
Copy link

erksch commented Jul 12, 2023

Hey thank you for this awesome property!

I wonder, why this does not freeze the second most-top screen in a stack navigator?

In stack, two top-most screens should console.log.

Is there a way to configure the freeze so it freezes all non-active screens in the stack navigator?

@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

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.

None yet

4 participants