Skip to content

Commit e08a83b

Browse files
Migrate 'Hooks' examples to static API in v7 (#1326)
--------- Co-authored-by: kacperkapusciak <kacper.kapusciak@swmansion.com>
1 parent a61d192 commit e08a83b

File tree

7 files changed

+1070
-48
lines changed

7 files changed

+1070
-48
lines changed

versioned_docs/version-7.x/use-focus-effect.md

Lines changed: 87 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,105 @@ title: useFocusEffect
44
sidebar_label: useFocusEffect
55
---
66

7+
import Tabs from '@theme/Tabs';
8+
import TabItem from '@theme/TabItem';
9+
710
Sometimes we want to run side-effects when a screen is focused. A side effect may involve things like adding an event listener, fetching data, updating document title, etc. While this can be achieved using `focus` and `blur` events, it's not very ergonomic.
811

912
To make this easier, the library exports a `useFocusEffect` hook:
1013

11-
<samp id="simple-focus-effect" />
14+
<Tabs groupId="config" queryString="config">
15+
<TabItem value="static" label="Static" default>
1216

13-
```js
17+
```js name="useFocusEffect hook" snack version=7
18+
import * as React from 'react';
19+
import { View } from 'react-native';
20+
import { createStaticNavigation } from '@react-navigation/native';
21+
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
22+
// codeblock-focus-start
1423
import { useFocusEffect } from '@react-navigation/native';
1524

16-
function Profile({ userId }) {
17-
const [user, setUser] = React.useState(null);
18-
25+
function ProfileScreen() {
1926
useFocusEffect(
2027
React.useCallback(() => {
21-
const unsubscribe = API.subscribe(userId, user => setUser(user));
28+
// Do something when the screen is focused
29+
return () => {
30+
// Do something when the screen is unfocused
31+
// Useful for cleanup functions
32+
};
33+
}, [])
34+
);
2235

23-
return () => unsubscribe();
24-
}, [userId])
36+
return <View />;
37+
}
38+
// codeblock-focus-end
39+
40+
function HomeScreen() {
41+
return <View />;
42+
}
43+
44+
const Tab = createBottomTabNavigator({
45+
screens: {
46+
Home: HomeScreen,
47+
Profile: ProfileScreen,
48+
},
49+
});
50+
51+
const Navigation = createStaticNavigation(Tab);
52+
53+
export default function App() {
54+
return <Navigation />;
55+
}
56+
```
57+
58+
</TabItem>
59+
<TabItem value="dynamic" label="Dynamic">
60+
61+
```js name="useFocusEffect hook" snack version=7
62+
import * as React from 'react';
63+
import { View } from 'react-native';
64+
import { NavigationContainer } from '@react-navigation/native';
65+
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
66+
67+
// codeblock-focus-start
68+
import { useFocusEffect } from '@react-navigation/native';
69+
70+
function ProfileScreen() {
71+
useFocusEffect(
72+
React.useCallback(() => {
73+
// Do something when the screen is focused
74+
return () => {
75+
// Do something when the screen is unfocused
76+
// Useful for cleanup functions
77+
};
78+
}, [])
2579
);
2680

27-
return <ProfileContent user={user} />;
81+
return <View />;
82+
}
83+
// codeblock-focus-end
84+
85+
function HomeScreen() {
86+
return <View />;
87+
}
88+
89+
const Tab = createBottomTabNavigator();
90+
91+
export default function App() {
92+
return (
93+
<NavigationContainer>
94+
<Tab.Navigator>
95+
<Tab.Screen name="Home" component={HomeScreen} />
96+
<Tab.Screen name="Profile" component={ProfileScreen} />
97+
</Tab.Navigator>
98+
</NavigationContainer>
99+
);
28100
}
29101
```
30102

103+
</TabItem>
104+
</Tabs>
105+
31106
:::warning
32107

33108
To avoid the running the effect too often, it's important to wrap the callback in `useCallback` before passing it to `useFocusEffect` as shown in the example.
@@ -107,7 +182,7 @@ useFocusEffect(
107182
React.useCallback(() => {
108183
return () => {
109184
// Do something that should run on blur
110-
}
185+
};
111186
}, [])
112187
);
113188
```
@@ -116,7 +191,7 @@ The cleanup function runs whenever the effect needs to cleanup, i.e. on `blur`,
116191

117192
```js
118193
React.useEffect(() => {
119-
const unsubscribe = navigation.addListener('blur', () => {
194+
const unsubscribe = navigation.addListener('blur', () => {
120195
// Do something when the screen blurs
121196
});
122197

@@ -146,7 +221,7 @@ function FetchUserData({ userId, onUpdate }) {
146221
// ...
147222

148223
class Profile extends React.Component {
149-
_handleUpdate = user => {
224+
_handleUpdate = (user) => {
150225
// Do something with user object
151226
};
152227

versioned_docs/version-7.x/use-is-focused.md

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,98 @@ title: useIsFocused
44
sidebar_label: useIsFocused
55
---
66

7+
import Tabs from '@theme/Tabs';
8+
import TabItem from '@theme/TabItem';
9+
710
We might want to render different content based on the current focus state of the screen. The library exports a `useIsFocused` hook to make this easier:
811

9-
<samp id="use-is-focused" />
12+
<Tabs groupId="config" queryString="config">
13+
<TabItem value="static" label="Static" default>
1014

11-
```js
15+
```js name="useIsFocused hook" snack version=7
16+
import * as React from 'react';
17+
import { View, Text } from 'react-native';
18+
import { createStaticNavigation } from '@react-navigation/native';
19+
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
20+
// codeblock-focus-start
1221
import { useIsFocused } from '@react-navigation/native';
1322

14-
// ...
23+
function ProfileScreen() {
24+
// This hook returns `true` if the screen is focused, `false` otherwise
25+
// highlight-next-line
26+
const isFocused = useIsFocused();
27+
28+
return (
29+
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
30+
<Text>{isFocused ? 'focused' : 'unfocused'}</Text>
31+
</View>
32+
);
33+
}
34+
// codeblock-focus-end
1535

16-
function Profile() {
36+
function HomeScreen() {
37+
return <View />;
38+
}
39+
40+
const Tab = createMaterialTopTabNavigator({
41+
screens: {
42+
Home: HomeScreen,
43+
Profile: ProfileScreen,
44+
},
45+
});
46+
47+
const Navigation = createStaticNavigation(Tab);
48+
49+
export default function App() {
50+
return <Navigation />;
51+
}
52+
```
53+
54+
</TabItem>
55+
<TabItem value="dynamic" label="Dynamic">
56+
57+
```js name="useIsFocused hook" snack version=7
58+
import * as React from 'react';
59+
import { View, Text } from 'react-native';
60+
import { NavigationContainer } from '@react-navigation/native';
61+
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
62+
// codeblock-focus-start
63+
import { useIsFocused } from '@react-navigation/native';
64+
65+
function ProfileScreen() {
66+
// This hook returns `true` if the screen is focused, `false` otherwise
67+
// highlight-next-line
1768
const isFocused = useIsFocused();
1869

19-
return <Text>{isFocused ? 'focused' : 'unfocused'}</Text>;
70+
return (
71+
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
72+
<Text>{isFocused ? 'focused' : 'unfocused'}</Text>
73+
</View>
74+
);
75+
}
76+
// codeblock-focus-end
77+
78+
function HomeScreen() {
79+
return <View />;
80+
}
81+
82+
const Tab = createMaterialTopTabNavigator();
83+
84+
export default function App() {
85+
return (
86+
<NavigationContainer>
87+
<Tab.Navigator>
88+
<Tab.Screen name="Home" component={HomeScreen} />
89+
<Tab.Screen name="Profile" component={ProfileScreen} />
90+
</Tab.Navigator>
91+
</NavigationContainer>
92+
);
2093
}
2194
```
2295

96+
</TabItem>
97+
</Tabs>
98+
2399
Note that using this hook triggers a re-render for the component when the screen it's in changes focus. This might cause lags during the animation if your component is heavy. You might want to extract the expensive parts to separate components and use [`React.memo`](https://reactjs.org/docs/react-api.html#reactmemo) or [`React.PureComponent`](https://reactjs.org/docs/react-api.html#reactpurecomponent) to minimize re-renders for them.
24100

25101
## Using with class component
@@ -35,7 +111,7 @@ class Profile extends React.Component {
35111
}
36112

37113
// Wrap and export
38-
export default function(props) {
114+
export default function (props) {
39115
const isFocused = useIsFocused();
40116

41117
return <Profile {...props} isFocused={isFocused} />;

0 commit comments

Comments
 (0)