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 in tsconfig.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 of flexGrow, flexShrink, and flexBasis, 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;