What is expo?
Ultimately a React Native app
Resources
Go here for good component library
- Timeline
- Wizard
- Card
What I’ve learned
- Create new app
npx create-expo-app@latest <name>
- Install library with
npx expo install <library>
- You can create styles and apply them to elements
<Text style={styles.text}>Hello world!</Text>
const styles = StyleSheet.create({
text: {
color: 'papayawhip'
}
})
_layout
defines shared elements like headers/footers- Each file added to
/app/
is a page in the app/web - Index files match their parent directory, so there can be multiple
- export default function
XLayout()
is probably important - Since documentation lacks it, here are some of the
Tabs
attributes
<Tabs
screenOptions={{
tabBarActiveTintColor: Colors.orange.default,
tabBarStyle: {
height: 70,
borderWidth: 1,
borderRadius: 50,
borderColor: Colors.orange.default,
borderTopColor: Colors.orange.default,
backgroundColor: Colors.white.default,
},
headerShadowVisible: false,
headerTintColor: '#fff',
tabBarStyle: {
tabBarLabelStyle: {
fontSize: 12,
fontWeight: "bold",
marginBottom: 10,
backgroundColor: '#25292e',
},
headerStyle: {
backgroundColor: '#25292e',
},
}}>
<Tabs.Screen
name="(HomeNav)"
options={{
title: "Home",
headerShown: false,
tabBarIcon: ({color, focused, size}) => (
<Ionicons name="ios-home" size={size} color={color}/>
),
}}/>
- For static images, you may fetch them with
require('@/assets/images/background-image.png');
@
is a path alias configured intsconfig.json
- In TypeScript, a question mark following a parameter indicates it is optional
- To create a react component, the “html” tag must be uppercase to be recognized. You may create a function with an uppercase starting name and return other react components.
<View style={{ flex: 1 }} />
has two curly braces, each for a different reason- The first is because this attribute expects a javascript expression
- The second is because style in particular expects a javascript object which is a collection of expressions
- Flex rundown:
flex: 1
is shorthand for making a component grow to fill available space.- Different
flex
values make components take up more or less space relative to each other (e.g. flex: 1 part of space vs flex: 2 parts of space) flex
is composed offlexGrow
,flexShrink
, andflexBasis
, these can be fine tuned individually
Library Specific
React Native Gesture Handler
<GestureHandlerRootView>
anything in here will be able to handle gestures
<GestureDetector gesture={drag}>
space that allows detection of gestures
drag
in this example is a const callback func for say, Gesture.Pan().onChange(event ⇒ <code>
)
import React from 'react';
import { View } from 'react-native';
import { GestureHandlerRootView, PanGestureHandler, PinchGestureHandler } from 'react-native-gesture-handler';
import Animated, { useSharedValue, useAnimatedStyle, useAnimatedGestureHandler, withSpring } from 'react-native-reanimated';
function DraggableSkillGraph() {
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const scale = useSharedValue(1);
const panHandler = useAnimatedGestureHandler({
onActive: (event) => {
translateX.value = event.translationX;
translateY.value = event.translationY;
},
onEnd: () => {
translateX.value = withSpring(translateX.value);
translateY.value = withSpring(translateY.value);
},
});
const pinchHandler = useAnimatedGestureHandler({
onActive: (event) => {
scale.value = event.scale;
},
onEnd: () => {
scale.value = withSpring(scale.value);
},
});
const animatedStyle = useAnimatedStyle(() => ({
transform: [
{ translateX: translateX.value },
{ translateY: translateY.value },
{ scale: scale.value },
],
}));
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<PanGestureHandler onGestureEvent={panHandler}>
<Animated.View style={[{ flex: 1 }, animatedStyle]}>
<PinchGestureHandler onGestureEvent={pinchHandler}>
<Animated.View style={{ flex: 1 }}>
<SkillGraph />
</Animated.View>
</PinchGestureHandler>
</Animated.View>
</PanGestureHandler>
</GestureHandlerRootView>
);
}
export default DraggableSkillGraph;