Software architect & consultant
Web / Mobile / VR / AR / IoT / AI
author, engineer, enterpreneur
CTO & Co-founder
creating a robust, performant, and feature-rich online conferencing experience
You did initial setup sent over by email and have Hello World app running
React Native combines the best parts of native development with React. You can use React Native today in your existing Android and iOS projects or you can create a whole new app from scratch.
React
JavaScript
JSC
Bridge
Shadow tree
JSON
Native Modules
Native
Start
Main Thread
load .js bundles and send to JS thread
React
Reconciler generates new VDOM layout
JS Thread
layout calculations
using Yoga
UI
updates
Shadow thread
Native modules
npx react-native init WhatsappProject
Yellow and Red boxes are disabled in production
To disable them in development:
/android - folder that stores Android native code
/ios - folder that stores Android native code
app.json - simulates Expo like config. Basically is imported by index.js
index.js - Entry point of application
AppRegistry registers app with native modules
Clone the repo:
Follow the instructions for Excercise 1 in the Readme.md
Style names and values usually match how CSS works (except transforms) except instead of kebab-case using camelCase.
container: {
flex: 1,
},
box1: {
flex: 1,
backgroundColor: 'red',
},
<View style={styles.container}>
<View style={styles.box1} />
</View>
container: {
flex: 1,
},
box1: {
flex: 1,
backgroundColor: 'red',
},
box2: {
flex: 1,
backgroundColor: 'orange',
},
<View style={styles.container}>
<View style={styles.box1} />
<View style={styles.box2} />
</View>
container: {
flex: 1,
},
box1: {
flex: 1,
backgroundColor: 'red',
},
box2: {
flex: 2,
backgroundColor: 'orange',
},
<View style={styles.container}>
<View style={styles.box1} />
<View style={styles.box2} />
</View>
container: {
flex: 1,
},
box1: {
flex: 1,
backgroundColor: 'red',
},
box2: {
flex: 2,
backgroundColor: 'orange',
},
<View style={styles.container}>
<View style={styles.box1} />
<View style={styles.box2} />
</View>
Continue from Excercise 1 solution
Clone step1 branch in the same repo
Follow the instructions for Excercise 2 in the Readme.md
or
Static resources can be auto sized
Dynamic resources need to have size provided
<Image
style={{
width: 51,
height: 51,
resizeMode: Image.resizeMode.contain,
}}
source={{
uri:'data:image/png;base64,iVBORw0KGg...',
}}
/>
cover - will take max value of either width or height and scale uniformly (maintain aspect ratio)
contain - will take min value of either width or height and scale uniformly (maintain aspect ratio)
stretch - scale width and height independently without conforming to aspect ratio
repeat - repeat the image to cover the frame of the view. image will keep size and aspect ratio
react-native-vector-icons
rm -rf android/app/build
<Icon
name="chat"
color="#fff"
size={23}
style={{ padding: 5 }}
/>
react-native-vector-icons
rm -rf android/ios/build
add to Info.plist
<key>UIAppFonts</key>
<array>
<string>AntDesign.ttf</string>
<string>Entypo.ttf</string>
<string>EvilIcons.ttf</string>
<string>Feather.ttf</string>
<string>FontAwesome.ttf</string>
<string>FontAwesome5_Brands.ttf</string>
<string>FontAwesome5_Regular.ttf</string>
<string>FontAwesome5_Solid.ttf</string>
<string>Foundation.ttf</string>
<string>Ionicons.ttf</string>
<string>MaterialIcons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
<string>SimpleLineIcons.ttf</string>
<string>Octicons.ttf</string>
<string>Zocial.ttf</string>
</array>
</dict>
<Icon
name="chat"
color="#fff"
size={23}
style={{ padding: 5 }}
/>
Continue from Excercise 2 solution
Clone step2 branch in the same repo
Follow the instructions for Excercise 3 in the Readme.md
or
Continue from Excercise 3 solution
Clone step3 branch in the same repo
Follow the instructions for Exercise 4 in the Readme.md
or
npm install @react-navigation/native
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
npx pod-install ios
npm install @react-navigation/stack
Instead specifying component you can use render callback
Second argument passed to navigate will be accessible on route.params inside screen component
You can also pass initialParams to a screen
Screen can update its params by using
navigation.setParams
More on params: https://reactnavigation.org/docs/params
Configuring headers: https://reactnavigation.org/docs/headers
Changing Header buttons:
Continue from Excercise 4 solution
Clone step4 branch in the same repo
Follow the instructions for Exercise 5 in the Readme.md
or
Create animated value
Create custom Animated component or use Animated.View
Add animated value as style
Trigger animation
Interpolate on value if needed
Continue from Excercise 5 solution
Clone step5 branch in the same repo
Follow the instructions for Exercise 6 in the Readme.md
or
A query language for your API
type Post {
title: String!
content: String!
user: User!
}
type Person {
name: String!
address: String
posts: [Post!]!
}
type Post {
title: String!
content: String!
user: User!
}
type Person {
name: String!
address: String
posts: [Post!]!
}
import {ApolloClient, InMemoryCache, split, HttpLink} from '@apollo/client';
import {getMainDefinition} from '@apollo/client/utilities';
import {WebSocketLink} from '@apollo/client/link/ws';
// Create an http link:
const httpLink = new HttpLink({
uri: 'endpoint url',
});
// Create a WebSocket link:
const wsLink = new WebSocketLink({
uri: 'endpoint url',
options: {
reconnect: true,
},
});
// The split function takes three parameters:
//
// * A function that's called for each operation to execute
// * The Link to use for an operation if the function returns a "truthy" value
// * The Link to use for an operation if the function returns a "falsy" value
const splitLink = split(
({query}) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink,
);
const cache = new InMemoryCache();
const client = new ApolloClient({
// Provide required constructor fields
cache: cache,
link: splitLink,
});
export default client;
import {useSubscription, gql, useMutation} from '@apollo/client';
const GET_MESSAGES_BY_ID = gql`
subscription getMessagesById($conversationId: uuid) {
messages(where: {conversation_id: {_eq: $conversationId}}) {
id
message
userId: user_id
}
}
`;
const POST_MESSAGE = gql`
mutation postMessageForUserId(
$userId: uuid
$conversationId: uuid
$message: String!
) {
insert_messages(
objects: {
user_id: $userId
conversation_id: $conversationId
message: $message
}
) {
returning {
message
}
}
}
`;
///
//
export const ChatViewScreen = ({navigation}) => {
const {id: conversationId} = route.params;
const {loading, data, error} = useSubscription(GET_MESSAGES_BY_ID, {
variables: {conversationId},
});
const [postMessage, {data: mutationData}] = useMutation(POST_MESSAGE);
<Compose
submit={(message) =>
postMessage({
variables: {
userId: MY_USER,
conversationId,
message,
},
})
}
/>
Continue from Excercise 6 solution
Clone step6 branch in the same repo
Follow the instructions for Exercise 7 in the Readme.md
or
@VladimirNovick