Contents
  1. 1. React navigation reset stack navigator
  2. 2. Use fetch
  3. 3. How to use Realm
  4. 4. How to debug
  5. 5. Screen auto Rotation
  6. 6. Tile swiper with dots
  7. 7. LaunchDarkly integration
  8. 8. File sharing
  9. 9. Upload aab to PlayStore
  10. 10. Upload ipa to AppStore

These are the React Native tricks I’ve found in the past 2 years.

React navigation reset stack navigator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/** From stack navigator definision **/
import {
CardStyleInterpolators,
createStackNavigator,
} from '@react-navigation/stack';

const Stack = createStackNavigator();

<Stack.Navigator
screenOptions={{
headerShown: false,
}}>
<Stack.Screen
name="ScreenA"
component={ScreenA}
options={{
cardStyleInterpolator: CardStyleInterpolators.forVerticalIOS,
}}
/>
<Stack.Screen
name="ScreenB"
component={ScreenB}
options={{
cardStyleInterpolator: CardStyleInterpolators.forVerticalIOS,
}}
/>
<Stack.Screen
name="ScreenC"
component={ScreenC}
options={{
cardStyleInterpolator: CardStyleInterpolators.forVerticalIOS,
gestureEnabled: false,
}}
/>
</Stack.Navigator>

The screen navigation order is ScreenA -> ScreenB -> ScreenC. If we want to navigation from ScreenC and reset the stack to SreenA, we can do the following in ScreenC.

1
2
3
4
5
6
navigation.dispatch(
CommonActions.reset({
index: 0,
routes: [{name: 'ScreenA'}],
}),
);

Use fetch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/** Fetch with timeout **/
export async function fetchWithTimeout(resource, options) {
const {timeout = 10000} = options; // 10 seconds
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
const response = await fetch(resource, {
...options,
signal: controller.signal,
});
clearTimeout(id);
return response;
}

/** General Graphql calls **/
export async function fetchGraphQL(
query,
variables,
timeout = 10000,
) {
// Fetch data from GitHub's GraphQL API:
const response = await fetchWithTimeout('BASE_API_URL', {
method: 'POST',
headers: {
Authorization: `bearer JWT_TOKEN`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: query,
variables,
}),
timeout: timeout,
});

const jsonResponse = await response.json();
// Get the response as JSON
return jsonResponse;
}

/** Real call**/
const response = await fetchGraphQL(
`mutation updateSomething(
$test: String!) {
updateSomething(
test: $test
)
}`,
{
test: 'test',
},
);

How to use Realm

1
2
3
4
5
6
7
8
9
/** Base Realm initiator **/
import Realm from 'realm';
import Test from '../Model/Test';

export default new Realm({
path: 'DB_NAME',
schema: [Test],
schemaVersion: 1,
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import Realm from 'realm';

export default class Test extends Realm.Object {
static schema = {
name: 'Test',
properties: {
ID: {type: 'int', default: 0},
Name: {type: 'string', default: ''},
},
primaryKey: 'ID',
};
}

export function getObjectById(DatabaseService, id) {
const tests = DatabaseService.objects('Test').filtered(
'ID ==[c] $0',
id,
);
if (tests && tests.length === 0) {
return null;
}
return convertRealmObjectToJson(tests[0], Test.schema.properties);
}

export function convertRealmObjectToJson(realmObject, schemaPropertyList) {
const result = {};
const keys = Object.keys(schemaPropertyList);
for (let key of keys) {
result[key] = realmObject[key];
}
return result;
}

How to debug

reactotron-react-native
https://github.com/infinitered/reactotron

Screen auto Rotation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/** Screen Component **/
import ScreenStyles from './ScreenStyles';

export default function DeviceScreen(props) {
const [styles, setStyles] = useState(ScreenStyles());
return (
<View
style={styles.container}
onLayout={event => {
setStyles(ScreenStyles());
}}>
</View>
);
}

/** Style component **/
export default function () {
/*
Do some screen detection and do proper styling with screen specific
*/

return StyleSheet.create({
container: {
flex: 1,
},
});
}

Tile swiper with dots

https://github.com/leecade/react-native-swiper
https://github.com/gusgard/react-native-swiper-flatlist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import React from 'react';
import {View, StyleSheet} from 'react-native';

export default function PaginationDots({length, activeIndex}) {
return (
<View style={Styles.container}>
{[...Array(length).keys()].map((_, i) => (
<View
key={i}
style={[
Styles.dot,
{
backgroundColor:
i !== activeIndex ? Colors.greenLight : Colors.charcoalGreen,
},
]}
/>
))}
</View>
);
}

const Styles = StyleSheet.create({
container: {
flexDirection: 'row',
},
dot: {
width: 10,
height: 10,
borderRadius: 10 / 2,
borderColor: 'black',
borderWidth: 1,
marginLeft: 5,
},
});

LaunchDarkly integration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import LDClient from 'launchdarkly-react-native-client-sdk';

export const LaunchDarklyClient = new LDClient();

export const initLaunchDarkly = async () => {
let config = {
mobileKey: PROD_MOBILE_KEY,
secondaryMobileKeys: {
qa: QA_MOBILE_KEY,
},
},
user = {
key: USER_KEY,
};
try {
await LaunchDarklyClient.configure(config, user, 5.0);
} catch (err) {
console.log('launchDarkly err', err);
}
};

const getBooleanValue = async (environment, key, defaultValue) => {
if (environment === 'QA') {
return await LaunchDarklyClient.boolVariation(key, defaultValue, 'qa');
} else {
return await LaunchDarklyClient.boolVariation(key, defaultValue);
}
};

File sharing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import RNFetchBlob from 'react-native-blob-util';
import RNFS from 'react-native-fs';
import Share from 'react-native-share';

export const shareWithIOS = async (
fileUrl,
file_name,
type = 'application/pdf',
) => {
let filePath = null;
const configOptions = {
fileCache: true,
path: RNFetchBlob.fs.dirs.DocumentDir + '/' + file_name,
};
try {
const response = await RNFetchBlob.config(configOptions).fetch(
'GET',
fileUrl,
);
filePath = response.path();
let options = {
type: type,
filename: file_name,
url: filePath,
};
await Share.open(options);
await RNFS.unlink(filePath);
} catch (error) {
console.log('error', error);
}
};

export const shareWithAndroid = async (
fileUrl,
file_name,
type = 'application/pdf',
) => {
let filePath = null;
const configOptions = {
fileCache: true,
path: RNFetchBlob.fs.dirs.DocumentDir + file_name,
};
try {
const response = await RNFetchBlob.config(configOptions).fetch(
'GET',
fileUrl,
);
filePath = response.path();

const base64Data = await response.readFile('base64');
const base64Url = `data:${type};base64,${base64Data}`;
let options = {
filename: file_name,
url: base64Url,
};
await Share.open(options);
await RNFS.unlink(filePath);
} catch (error) {
console.log('error', error);
}
};

Upload aab to PlayStore

1
2
3
4
/** fastlane/AppFile **/
json_key_file("./google-key.json")
package_name("ANDROID_APP_ID")

1
fastlane supply --aab app-release.aab --track alpha

Upload ipa to AppStore

1
xcrun altool --upload-app --type ios --file YOUR_APP.ipa --username "APPLE_ID" --password "APPLE ID PWD"
Contents
  1. 1. React navigation reset stack navigator
  2. 2. Use fetch
  3. 3. How to use Realm
  4. 4. How to debug
  5. 5. Screen auto Rotation
  6. 6. Tile swiper with dots
  7. 7. LaunchDarkly integration
  8. 8. File sharing
  9. 9. Upload aab to PlayStore
  10. 10. Upload ipa to AppStore