0%

COSI 153A Mobile Development

Lesson 01 2021/08/30

  1. Install Node.js
  2. Install GitHub Desktop
  3. Run react-native app
    • Run on browser: use React Native website, or use snack.expo.dev
    • Run locally using Expo CLI
      • Install Expo CLI: npm install -g expo-cli
      • Create a new React Native project and run
        1
        2
        3
        4
        5
        expo init ProjectName

        cd ./ProjectName

        npm start # expo start is also okay
    • Run one your phone: download Expo Go and scan the QR code

Lesson 02 2021/09/01

  1. Scope
  2. Introduction
    • Intro
      • React Native is an open source framework for building Android and iOS applications using React and the app platform’s native capabilities
      • With React Native, you use JavaScript to access your platform’s APIs as well as to describe the appearance and behavior of your UI using React components
    • View
      • In mobile development, a view is a basic building block of UI: a rectangular element on the screen which can be used to display text, images, or respond to user input
      • Views can be nested
    • Native Components
      • You can invoke Andriod and iOS components with JS using React components, React Native creates the corresponding Andriod and iOS components at runtime. We call these platform-backed components Native Components
      • React Native comes with a set of essential, ready-to-use Native Components you can use to start building your app today. These are React Native's Core Components
      • React Native lets you build your own Native Components for Android and iOS to suit your app’s unique needs
      • React Native has a thriving ecosystem of community-contributed components
  3. Core Components
    • View

      • View is the most fundamental component for building a UI. It is a container that supports layout with flexbox, style, some touch handling, and accessibility controls
      • View is designed to be nested inside other views and can have 0 to many children of any type
      • Basic example
        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
        import React from 'react';
        import {View, Text, StyleSheet} from 'react-native';

        const ViewApp = () => {
        return (
        // It is recommended to use StyleSheet for clarity and performance
        <View style ={styles.container}>
        // Inline styles are also supported
        <Text style ={{fontSize: 40, fontWeight:'bold'}}>
        Try editing me!
        </Text>

        </View>
        );
        };

        styles = StyleSheet.create({
        container: {
        backgroundColor: 'red',
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center'
        }
        });

        export default ViewApp;
    • Text

      • Text is a React component for displaying text
      • Text supports nesting, styling, and touch handling
      • Limited Style Inheritance: in order to inherit styles from parent components, you must wrap all the text nodes inside of a Text component, you cannot have a text node directly under a View.
      • Basic Example
        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 React from 'react';
        import {View, Text, StyleSheet} from 'react-native';

        const TextApp = () => {
        return (
        <View style={styles.container}>
        <Text style={styles.baseText}>
        This is a
        <Text style={styles.innerText}>
        paragraph!
        </Text>
        </Text>
        </View>
        );
        };

        export default TextApp;

        const styles = StyleSheet.create({
        container: {
        backgroundColor: 'lightblue',
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        },
        baseText: {
        fontWeight: 'bold',
        },
        innerText: {
        fontSize: 20,
        color: 'red',
        },
        });
    • TextInput

      • TextInput is a foundational component for inputting text into the app via a keyboard
      • Basic Example
        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
        import React from "react";
        import { View, StyleSheet, TextInput, Text } from "react-native";

        const TextInputApp = () => {
        return (
        <View style ={styles.container}>
        <label >
        Enter Your Name.
        </label>
        <TextInput style={styles.input} placeholder="Jesse Li" />
        </View>
        );
        };

        export default TextInputApp;

        const styles = StyleSheet.create({
        container: {
        backgroundColor:'lightblue',
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        },
        input: {
        backgroundColor:'yellow',
        borderColor: 'black',
        borderRadius: 5,
        }
        });
    • Image

      • Image is a React component for displaying different types of images, including network images, static resources, temporary local images, and images from local disk, such as the camera roll
      • Static image
        1
        2
        3
        4
        5
        6
        // project structure
        // ├── app.js
        // └── img
        // ├── my-icon.png
        // in app.js
        <Image source={require('./img/my-icon.png')} />
      • Network image
        1
        2
        3
        // You should mannually give the image its size
        <Image source={{uri: 'https://reactjs.org/logo-og.png'}}
        style={{width: 400, height: 400}} />
    • ScrollView

      • ScrollViews must have a bounded height in order to work, it is recommended that all parent containers have a bound height
      • Basic Example
        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
        import React from 'react';
        import {StyleSheet, View, ScrollView,Text} from 'react-native';

        const ScrollViewApp = () => {
        return (
        <View style={styles.container}>
        <ScrollView style={styles.scroolview}>
        <Text style={styles.text}>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
        eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
        minim veniam, quis nostrud exercitation ullamco laboris nisi ut
        aliquip ex ea commodo consequat. Duis aute irure dolor nin
        reprehenderit nin voluptate velit esse cillum dolore eu fugiat nulla
        pariatur. Excepteur sint occaecat cupidatat non proident, sunt nin
        culpa qui officia deserunt mollit anim id est laborum.
        </Text>
        </ScrollView>
        </View>
        );
        };

        const styles = StyleSheet.create({
        container: {
        flex: 1,
        },
        scroolview: {
        backgroundColor: 'lightblue',
        },
        text: {
        fontSize: 42,
        },
        });

        export default ScrollViewApp;
    • Button

      • A basic button component that should render nicely on any platform
      • Basic Example
        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
        import React from 'react';
        import { StyleSheet, Button, View, Text, Alert } from 'react-native';

        const App = () => (
        <View style={styles.container}>
        <View>
        <Text style={styles.title}>
        The title and onPress handler are required. It is recommended to set accessibilityLabel to help make your app usable by everyone.
        </Text>
        <Button
        title="Press me"
        onPress={() => Alert.alert('Simple Button pressed')}
        />
        </View>
        <View>
        <Text style={styles.title}>
        All interaction for the component are disabled.
        </Text>
        <Button
        title="Press me"
        // Then this button cannot be pressed
        disabled
        onPress={() => Alert.alert('Cannot press this one')}
        />
        </View>
        </View>
        );

        const styles = StyleSheet.create({
        container: {
        flex: 1,
        justifyContent: 'center',
        marginHorizontal: 16,
        },
        title: {
        textAlign: 'center',
        marginVertical: 8,
        },
        });

        export default App;
    • StyleSheet

      • A StyleSheet is an abstraction similar to CSS StyleSheets
  4. Flexbox
    • flex
      • flex: N, occupies \(\frac{N_i}{\sum{N_i}}\) space of row or column depending on flexDirection
    • flexDirection
      • flexDirection: column, default, main axis is column, from top to bottom
      • flexDirection: row, main axis is row, from left to right
      • flexDirection: column-reverse: main axis is column, from bottom to top
      • flexDirection: row-reverse: main axis is row, from right to left
    • justifuContent
      • justifyContent: flex-start, default, children starts from start of main axis
      • justifyContent: flex-end, children starts from end of main axis
      • justifyContent: center, aligns children in the center of main axis
      • justifyContent: space-between, no space before the first children and after the last children
      • justifyContent: space-around, half space before the first children and after the last children
      • justifyContent: space-evenly, all space is evenly divided
    • alignItems
      • alignItems: stretch, default, stretch children to match the height of the container's cross axis
      • alignItems: flex-start, children starts from the start of the cross axis
      • alignItems: flex-end, children starts from the end of the cross axis
      • alignItems: center, align children in the center of the container's cross axis
      • alignItems: flex-start, align children along a common baseline
    • alignContent: distribution on the cross axis, only has effect when flexWrap: wrap
    • flexWrap, flexWrap: wrap or flexWrap: nowrap
    • flexBasis, flexGrow, flexShrink
    • width, height, default auto, can also set to integer pixels(eg width: 300) or string percentage(eg width: "80%")
    • position: defines how an element is positioned within its parent
      • position: relative, default
      • position: absolute

Lesson 03 2021/09/13

  1. Steps to design a page
    • Decide on the top level components and if they will be laid out horizontally or vertically.
    • Decide on the justifyContent values (for the main axis) and the alignItem values for the cross-axis
    • Create the toplevel components (possibly view) and use the grid property to state the relative size of that component.
    • Repeat the process for each of the toplevel components, which can themselves consist of embedded components.
    • Select colors, borders, fonts, and other style elements for the core components (Text, Button, TextInput, etc.)

Lesson 04 2021/09/15

  1. Introduction to Navigator
    • Managing the presentation of, and transition between, multiple screens of a mobile app is typically handled by what is known as a navigator
    • React Navigation provides a straightforward navigation solution, with the ability to present common stack navigation and tabbed navigation patterns on both Android and iOS
  2. React Navigation
    • Installation: npm install @react-navigation/native
    • Installation of dependent libraries
      • Install into an Expo managed project: expo install react-native-screens react-native-safe-area-context
      • Install into a bare React Native project: npm install react-native-screens react-native-safe-area-context
    • Basic Example
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      import * as React from 'react';
      import { NavigationContainer } from '@react-navigation/native';

      const App = () => {
      return (
      <NavigationContainer>
      {/* Rest of your app code */}
      </NavigationContainer>
      );
      };

      export default App;
    • The Navigation logic
      • Web browser nagivator
        • When a link is clicked, the browser jumps to a new page, the URL is pushed to the browser history stack
        • When the back button is clicked, the browser pops the item from the top of the history stack
      • React Navigation's native stack navigator does the same things, it also provides gestures and animations when navigating between routes in the stack
    • The native stack navigator
      • Installation: npm install @react-navigation/native-stack
      • Basic Example
        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
        import * as React from 'react';
        import { View, Text, Button } from 'react-native';
        import { NavigationContainer } from '@react-navigation/native';
        import { createNativeStackNavigator } from '@react-navigation/native-stack';

        // In the native stack navigator, each Screen has a navigation property
        const HomeScreen = ({navigation}) => {
        return (
        <View>
        <Text> Home Screen </Text>
        <Button
        title = "Go to details"
        // Call the navigate function to move between pages, if the destination is the current page, navigate method does nothing
        onPress={() => navigation.navigate('Details')}
        />
        </View>
        );
        };

        const DetailsScreen = () => {
        return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Details Screen</Text>
        <Button
        title = "Go to details"
        // Call the push function to move between pages, this method can go to the same page multiple times
        onPress={() => navigation.push('Details')}
        />
        </View>
        );
        }

        // This function returns an object with two properties: Screen and Navigator
        const Stack = createNativeStackNavigator();

        const App = () => {
        return (
        // NavigationContainer manages the navigation tree and contains the navigation state
        <NavigationContainer>
        // Navigator should contain Screen to define the configuration for routes
        <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
        </Stack.Navigator>
        </NavigationContainer>
        );
        }

        export default App;
      • Go to a page: navigation.navigate("pageName")
      • Go to a page including the current one: navigation.push("pageName")
      • Go back to the previous page: navigation.goBack()
      • Go back to the first screen in the stack: navigation.popToTop()

Lesson 05 2021/09/20

  1. Example
    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    import React, { useState } from 'react';
    import { View, Text, Button, StyleSheet, TextInput } from 'react-native';
    import { NavigationContainer } from '@react-navigation/native';
    import { createNativeStackNavigator } from '@react-navigation/native-stack';

    const HomeScreen = ({ navigation }) => {
    return (
    <View style={styles.container}>
    <Text> Welcome to the home screen!</Text>
    <Button
    title="Go to Details"
    onPress={() => navigation.navigate('Details')}
    />
    </View>
    );
    };

    const DetailsScreen = (props) => {
    const [count, setCount] = useState(0);
    const [count1, setCount1] = useState(0);

    return (
    <View style={styles.container}>
    <Text>Count = {count}</Text>

    <Button
    color="red"
    title="Increment"
    onPress={() => setCount(count + 1)}
    />
    <Text>Count = {count1}</Text>
    <Button
    color="red"
    title="Increment"
    onPress={() => setCount1(count1 - 1)}
    />
    <Button
    color="red"
    title="Reset"
    onPress={() => {
    setCount(0);
    setCount1(0);
    }}
    />
    </View>
    );
    };

    const Stack = createNativeStackNavigator();

    const App = () => {
    return (
    <NavigationContainer>
    <Stack.Navigator initialRouteName="Home">
    <Stack.Screen name="Home" component={HomeScreen} />
    <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
    </NavigationContainer>
    );
    };

    const styles = StyleSheet.create({
    container: {
    flex: 1,
    backgroundColor: 'yellow',
    justifyContent: 'space-evenly',
    alignItems: 'center',
    },
    });

    export default App;

Lesson 06 2021/09/22

Lesson 07 2021/09/29

  1. Asynchronous Storage
    • Installation
      • npm install @react-native-async-storage/async-storage

Lesson 08 2021/10/04

  1. Context and Data Sharing
    • In a typical React application, data is passed top-down (parent to child) via props, but such usage can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application.
    • Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree
    • When to use context: Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language
    • Before you use context: If you only want to avoid passing some props through many levels, component composition is often a simpler solution than context
      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
      // This one is tedious
      <Page user={user} avatarSize={avatarSize} />
      // ... which renders ...
      <PageLayout user={user} avatarSize={avatarSize} />
      // ... which renders ...
      <NavigationBar user={user} avatarSize={avatarSize} />
      // ... which renders ...
      <Link href={user.permalink}>
      <Avatar user={user} size={avatarSize} />
      </Link>

      // This one is better
      function Page(props) {
      const user = props.user;
      const userLink = (
      <Link href={user.permalink}>
      <Avatar user={user} size={props.avatarSize} />
      </Link>
      );
      return <PageLayout userLink={userLink} />;
      }

      // Now, we have:
      <Page user={user} avatarSize={avatarSize} />
      // ... which renders ...
      <PageLayout userLink={...} />
      // ... which renders ...
      <NavigationBar userLink={...} />
      // ... which renders ...
      {props.userLink}
    • API:
      • React.createContext: Creates a Context object. When React renders a component that subscribes to this Context object it will read the current context value from the closest matching Provider above it in the tree.
        1
        const MyContext = React.createContext(defaultValue);
      • Context.Provider: Every Context object comes with a Provider React component that allows consuming components to subscribe to context changes. The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers. Providers can be nested to override values deeper within the tree.
        1
        <MyContext.Provider value={/* some value */}>
      • Context.Consumer: A React component that subscribes to context changes. Using this component lets you subscribe to a context within a function component.
        1
        2
        3
        <MyContext.Consumer>
        {value => /* render something based on the context value */}
        </MyContext.Consumer>
    • useContext hook: Accepts a context object (the value returned from React.createContext) and returns the current context value for that context. The current context value is determined by the value prop of the nearest <MyContext.Provider> above the calling component in the tree. useContext(MyContext) is equivalent to <MyContext.Consumer>.
      1
      const value = useContext(MyContext);

Lesson 09 2021/10/06

  1. Device specific options
    • https://docs.expo.dev/versions/latest/

Lesson 10 2021/10/11

  1. JavaScript module
    • As programs become more complicated, it's useful to provide mechanisms for splitting JavaScript programs up into separate modules that can be imported when needed
      • Node.js, CommonJS, RequireJS all supports modules
      • Modern browsers have started to support module functionality natively
      • Use of native JavaScript modules is dependent on the import and export statements
    • Exporting module features
      • The first thing you do to get access to module features is export them. This is done using the export statement
      • The easiest way to use it is to place it in front of any items you want exported out of the module
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        // suppose the relative path is "./modules/square.js"
        export const name = 'square';

        export function draw(ctx, length, x, y, color) {
        ctx.fillStyle = color;
        ctx.fillRect(x, y, length, length);

        return {
        length: length,
        x: x,
        y: y,
        color: color
        };
        }
      • You can export functions, var, let, const, and classes
      • A more convenient way of exporting all the items you want to export is to use a single export statement at the end of your module file, followed by a comma-separated list of the features you want to export wrapped in curly braces
        1
        export {name, draw};
    • Importing features into your script
      • Once you've exported some features out of your module, you need to import them into your script to be able to use them
      • You use the import statement, followed by a comma-separated list of the features you want to import wrapped in curly braces, followed by the keyword from, followed by the path to the module file — a path relative to the site root
        1
        import { name, draw } from "./modules/square.js";
      • In some module systems, you can omit ./, ../, .js, but this does not work in native JavaScript
      • Although imported features are available in the file, they are read only views of the feature that was exported
    • Applying the module to your HTML
      • You need to include type="module" in the <script> element
      • Method 1: reference a script
        1
        <script type="module" src="./script.js"></script>
      • Method 2: directly embed a module in the HTML file
        1
        2
        3
        <script type="module">
        // JavaScript code here
        </script>
    • Default exports v.s. named exports
      • Default export: designed to make it easy to have a default function provided by a module, and also helps JavaScript modules to interoperate with existing CommonJS and AMD module systems
        • There is only one default export allowed per module
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          // Method 1
          export default const name = "Square";
          // Method 2
          const name = "Square";
          export default name;

          // Shorthand import for default feature
          import name from "./modules/square.js";
          // Full import statement for default feature
          import { default as name } from "./modules/square.js";
      • Named export: each item is referred to by its name upon export
    • Avoiding naming conflicts
      • If you try to import different functions of the same name into the same top-level module file, you would end up with conflicts and errors
      • Rename exports and imports
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
               // Method 1
        export { function1 as newFunction1, function2 as newFunction2 };
        import { newFunction1, newFunction2 } from "./modules/function.js";
        // Method 2
        export { function1, function2};
        import { function1 as newFunction1, function2 as newFunction2} from "./modules/function.js";
        ````
        * Create a module object
        ```javascript
        export { function1, function2 };
        import * as Function from "./modules/function.js";
        Function.function1();
        Function.function2();
    • Modules and Classes
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      class Square {
      constructor(ctx, listId, length, x, y, color) {
      ...
      }

      draw() {
      ...
      }

      ...
      }
      export { Square };

      import { Square } from "./modules/square.js";
  2. class
    • Classes are a template for creating objects
    • Functions can be called in code that appears before they are defined, classes must be defined before they can be constructed
    • Class declarations
      1
      2
      3
      4
      5
      6
      class Rectangle {
      constructor(height, width) {
      this.height = height;
      this.width = width;
      }
      }
    • Class expressions
      1
      2
      3
      4
      5
      6
      let Rectangle = class {
      constructor(height, width) {
      this.height = height;
      this.width = width;
      }
      };
    • Class body
      • Constructor
      • Fields and methods
      • Use # for private field
      • Use extends for inheritance
      • Use this and super keywords when necessary

Lesson 11 2021/10/13

  1. function
    • Defining functions
      • Function declarations
        1
        2
        3
        function square(number) {
        return number * number;
        }
      • Function expressions
        1
        2
        3
        const square = function(number) {
        return number * number;
        }
      • Arrow functions
        1
        2
        3
        const square = (number) => {
        return number * number;
        }
    • Function parameters
      • Default parameters
      • Rest parameters ...theArgs
  2. closure
    • A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function
      1
      2
      3
      4
      5
      6
      7
      function makeAdder(x) {
      return function(y) {
      return x + y;
      };
      }
      var add5 = makeAdder(5);
      add5(2); // 7
    • Closure scope chain
      • Local Scope (Own scope)
      • Outer Functions Scope
      • Global Scope
  3. User-defined components
    • Function components
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      import React from 'react';
      import { Text } from 'react-native';

      const Cat = () => {
      return (
      <Text>Hello, I am your cat!</Text>
      );
      }

      export default Cat;
    • Class component
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      import React, { Component } from 'react';
      import { Text } from 'react-native';

      class Cat extends Component {
      render() {
      return (
      <Text>Hello, I am your cat!</Text>
      );
      }
      }

      export default Cat;
    • Use state with class components
      • Declare the state: state = { key: value };
      • Use the state: this.state.key
      • Set the state: this.setState({ key: value });
  4. You can have conditional rendering with useState hook

Lesson 12 2021/10/18

  1. Ideas
    • Each app will have its own appKey,so data can be shared between users of the app
    • Each device will have its own userKey, so users can access their own data on the cloud
    • Users can store and retrieve data with a valueKey and a String value, just as with AsyncStorage but the data will be stored in the cloud and they can share data with each other
    • Server: Heroku, database: MongoDB
  2. Axios
    • Use axios is more easier than the built-in fetch function
    • Usage
      1
      2
      const z = await Axios.get(URL)  # to get data from the server using only the URL
      const z = await Axios.post(URL,JSONdata) # to send data to server and get something back
    • For a browser, you can only have get and post, for mobile phones, you can have more HTTP verbs
  3. Get and retrieve data from server
    • Store and export appKey and appUrl locally on the device
    • Use the following code
      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
      63
      64
      65
      66
      67
      import React, { useState, useEffect } from "react";
      import { Button, StyleSheet, Text, TextInput, View } from "react-native";
      import AsyncStorage from '@react-native-async-storage/async-storage';
      import Axios from 'axios'
      import { appKey, appURL } from '../lib/appKey.js'


      const CloudRegistration = () => {
      const [userKey, setUserKey] = useState(null)


      useEffect(() => {
      clearAll();
      getData();}
      ,[])

      const storeData = async (key,value) => {
      try {
      await AsyncStorage.setItem(key, jsonValue)
      } catch (e) {
      console.dir(e)
      }
      }

      const getData = async () => {
      try {
      let data = await AsyncStorage.getItem('@userKey')
      if (Object.keys(data).length === 0) {
      setUserKey(data.userKey)
      } else {
      let result =
      await Axios.post(appURL + '/getNewUserKey', { appKey : appKey })
      setUserKey(result.data.userKey)
      await AsyncStorage.setItem(key, result.data)
      }
      } catch(e) {
      console.dir(e)
      }
      }

      const clearAll = async () => {
      try {
      await AsyncStorage.clear()
      } catch(e) {
      console.dir(e)
      }
      }

      let registrationComponent = <Text>initializing userKey:{userKey}</Text>
      if (userKey) {
      registrationComponent =
      <View>
      <View style={{flexDirection : 'row', flex : 1, justifyContent : 'space-around'}}>
      <Text>UserKey = {userKey} </Text>
      <Button title="clear user key (Dangerous only for debugging)"
      color='red'
      onPress = {() => {clearAll()}} />
      </View>
      </View>
      }

      return (
      { registrationComponent }
      )

      }
      export default CloudRegistration;

Lesson 13 2021/10/20

  1. Idea
    • Check asynchronous storage, if there is not data, fetch from cloud storage

Lesson 14 2021/11/01

  1. Container components
    • Example
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      import React from "react";
      import { SafeAreaView, View} from 'react-native'

      const ScreenTemplate = ({header,footer,children}) => {
      return (
      <SafeAreaView style={{flex:1,padding:0,margin:0}}>
      {header}
      <View style={{flex:1, backgroundColor:"#eee"}}>
      {children}
      </View>
      {footer}
      </SafeAreaView>
      )
      }
      export default ScreenTemplate;
      // Then you can use like this:
      import ScreenTemplate from "./containers/screenTemplate.js";
      <ScreenTemplate
      header={}
      footer={}
      children ={}
      />
  2. Javascript concepts from the book <<Modern JavaScript for the Impatient>>
    • Chapter 1 Values and Variables
      • Types: number, boolean, undefined/null, string, symbol, object
      • Comments
        • Single line: //
        • Multiple line: /* */
      • Variable declaration
        • Declared but not assigned variables have value of undefined
        • Use let or constant, do not use var
      • Numbers are all double-precision floating-point numbers
        1
        2
        3
        4
        5
        6
        // convert string to numbers
        let x = 3.14
        const y = parseFloat(x);
        const z = parseInt(x);
        // convert number to string
        const c = y.toString();
      • null and undefined
        • Use null to denote the intentional absence of value
        • Use undefined to indicate a declared but not assigned variable
      • Template literal
        1
        2
        let x = "world";
        let greeting = `Hello, ${x.toUpperCase()}`;
      • Objects
        • Objects in JavaScript are simply key/value pairs or properties
        • The key should be a string
      • JSON
        • JavaScript Object Notation is a lightweight text format of exchanging object data between applications
        • All strings are inside double quotes
        • Convert JavaScript object into JSON: JSON.stringify(object)
        • Convert JSON string to JavaScript object: JSON.parse(json)
      • Destructing
        • Swap the value of two variables: [x, y] = [y, x]
        • Rest declarations
          1
          2
          3
          4
          const nums1 = [1,2,3,4];
          let [x, y, ...others] = nums1; // others is [3,4]
          const nums2 = [1,2]
          let [x, y, ...others] = nums2; // others is []
    • Chapter 2 Control Structures
      • Any comparison involving NaN yields false
      • If one operand is a number, the other operand is converted to a number
        1
        2
        3
        4
        "" < 5; // true, "" is converted to 0
        "Hello" < 5, // false, "Hello" is converted to NaN
        [] < 5 // true, [] is converted to 0
        [1, 2] < 5 // false, [1, 2] is converted to NaN
      • If neither operand is a number, both are converted to strings
        1
        [1, 2, 3] < {} // true, [1, 2, 3] is converted to '1,2,3', {} to '[object Object]'
      • Statements
        • if else
        • switch
        • for
          • for of: used on iterable object, most commonly an array or string
          • for in: used on properties of object
        • while
        • do while
        • break, continue
        • try catch
    • Chapter 3 Functions and Functional Programming
      • Functional array processing
        1
        2
        3
        const arr = [1, 2, 3];
        const arr1 = arr.map(x => x * x); // arr1 is [1, 4, 9]
        arr.forEach(ele => {console.log(ele);})
      • Put "use strict" in your file to enable strict mode
      • Test types
        1
        2
        3
        4
        5
        6
        7
        8
        let x = "abc";  
        // method 1
        typeof x === 'string'; // true
        // method 2
        x instanceof String; // false

        typeof [] === "string"; // true
        [] instanceof String; // true
      • Rest parameters and spread operator
        1
        2
        3
        4
        5
        6
        7
        8
        9
        const avg = (first = 0, ...others) => {
        let sum = first;
        for (let value of others) {
        sum += value;
        }
        return sum / (1 + others.length);
        }

        avg([1,2,3]); // return 2
        1
        2
        3
        4
        let result = Math.max(1, 2, 3); // 3
        const nums = [1, 2, 3];
        result = Math.max(nums); // NaN, max cannot calculate maximum of one array
        result = Math.max(...nums); // 3, use ... operator to destruct the array
      • Exceptions
        • Throw: throw Error(reasonString)
        • Catch
        • Finally
    • Chapter 9 Asynchronous Programming
      • Concurrent tasks
        • A program is concurrent when it manages multiple activities with overlapping timelines
        • A JavaScript program runs in a single thread, so time-consuming operations in JavaScript are asynchronous
      • Promise
        • A promise is an action that will produce a result at some point in the future, unless it dies with an exception
        • A promise has a resolve handler and a reject handler
          1
          2
          3
          4
          5
          6
          7
          8
          // template
          const myPromise = new Promise((resolve, reject) => {
          const callback = (args) => {
          . . .
          if (success) resolve(result) else reject(reason)
          }
          invokeTask(callback)
          })
        • You can use promise chain with .then
      • Async functions
        • Use await/async syntax with promise and asynchronous functions
        • Usage
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          // Arrow functions
          async (url) => {...}
          // Methods
          class Test {
          async load(url) {...}
          }
          // Named functions
          async function load(url) {...}
          // Object literal methods
          const obj = {
          async load(url) {...}
          }
      • Async return values
        • An async function returns a promise
        • In the fetch API, you should use await result.json(), because JSON is processing asynchronously
      • Concurrent await
        • Successive calls to await are done one after another, you can let them execute concurrently when necessary
          1
          2
          3
          4
          5
          // Sequential execution
          const img1 = await loadImage(url1);
          const img2 = await loadImage(url2);
          // Concurrent execution
          const [img1, img2] = await Promise.all(loadImage(url1), loadImage(url2));
    • Chapter 10 Modules
      • The module concept
        • A module provides features for programmers, called the exported features. Any features that are not exported are private to the module
        • A module also specified on which other modules it depends
        • Modules manage name conflicts
      • ECMAScript modules
        • Node.js implements a module system (called Common.js) that manages module dependencies. When a module is needed, it and its dependencies are loaded synchronously
        • The AMD (Asynchronous Module Definition) standard defines a system for loading modules asynchronously, which is better suited for browser-based applications
        • ECMAScript modules improve on both of these systems

Lesson 15 2021/11/03

  1. Express
    • MERN stack
    • Express is a fast, unopinionated, minimalist web framework for Node.js
    • Installation
      • npm install express --save for express
      • npm install -g express-generator for the express-generator
      • You can run your file with express using node xxx.js, express-generator creates the scaffolding for a full app with numerous JavaScript files, Jade templates, and sub-directories for various purposes
      • Create express project using express-generator
        • express projectName
        • cd projectName, then npm install
        • Start
          • On MacOS or Linux: DEBUG=projectName:* npm start
          • Windows Command Prompt: set DEBUG=projectName:* & npm start
          • Windows PowerShell: $env:DEBUG='projectName:*'; npm start
          • Or simply: npm start
    • Example app.js
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      const express = require('express')
      const app = express()
      const port = 3000

      app.get('/', (req, res) => {
      res.send('Hello World!')
      })

      app.listen(port, () => {
      console.log(`Example app listening at http://localhost:${port}`)
      })
    • Some settings
      1
      2
      3
      4
      5
      6
      var path = require('path');
      // view engine setup
      app.set('views', path.join(__dirname, 'views'));
      app.set('view engine', 'ejs');

      module.exports = app;
    • Import and require
      • Express is based on Node.js, the module system syntax in Node.js is require
      • Plain JavaScript is based on ES6, the module system syntax is import and export
      • import must be at the beginning of a file, but require can be anywhere in a file
    • API
      • app.get(): Routes HTTP GET requests to the specified path with the specified callback functions
        1
        2
        3
        4
        5
        let counter = 0;
        app.get('path', async (req, req) => {
        counter += 1;
        res.send(`Counter = ${counter} `);
        })
      • app.post(): Routes HTTP POST requests to the specified path with the specified callback functions
        1
        2
        3
        4
        5
        6
        7
        8
        let messages = [];
        app.use("/messages",
        async (req, res) => {
        let msg = req.body;
        messages.push(msg);
        res.json(messages);
        }
        );
  2. SQL vs NoSQL database
    • Difference
      • SQL db is relational, NoSQL db is not relational
      • SQL db is based on table, NoSQL db can be based on document, key/value pair
      • There is automatic sql optimization in sql db
    • MondoDB
      • Local Server Installation
        • Download and install MongoDB
        • To use in shell, install MongoDB shell(mongosh)
      • MongoDB Atlas(Cloud version)
        • Create new database
        • Configure database access and network access
        • Connection:
          • Download MongoDb compass and use that to connect MongoDB Atlas
          • Connect using mongosh
      • Shell CRUD commands
        • Query databases: show dbs;
        • Switch to one database: use dbName;
        • Query collections: show collections;
        • Read: query document:
          • Query all: db.cName.find({});, or db.cName.find(); this is just select * from cName;
          • Query with equal condition: db.cName.find({key: value});, this is just select * from cName where key = value;
          • Query with and: db.cName.find({k1: v1, k2: {$lt: v2}});, this is just select * from cName where k1 = v1 and k2 < v2;
          • Query with or: db.cName.find({$or: [{k1: v1}, {k2: {$gt: v2}}]});, this is just select * from cName where k1 = v1 or k2 > v2;
        • Create: insert document:
          • Insert one document: db.cName.insertOne({k1 : v1, ..., kn: vn});, this is just insert into cName (k1, ..., kn) values (v1, ..., vn);
          • Insert multiple documents: db.cName.insertMany({k11: v11, ..., k1n: v1n}, ..., {km1: vm1, ..., kmn: vmn});, this is just insert into cName(k1, ..., kn) values (v11, ..., v1n), ... ,(vm1, ..., vmn);
        • Update: update document
          • Update one document: db.cName.updateOne({k1 : v1}, {$set: {k1: k2}, $inc: {k2: 1}}), this is just update cName set k1 = v2, k2 = k2 + 1 where k1 = v1;
          • Update multiple documents: db.cName.updateMany({k1: v1}, {$set: {k1: v2}}), this is just update cName set k1 = v2 where k1 = v1;
        • Delete: delete document
          • Delete one document: db.cName.deleteOne({k1: v1});, this is just delete from cName where k1 = v1;
          • Delete multiple documents: db.cName.deleteMany({k1: v1});, this is just delete from cName where k1 = v1;
    • Connect MongoDB in Express
      • npm install mongodb in project directory
      • Add the following code in app.js
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
         const { MongoClient } = require('mongodb');
        const uri = "urlString";
        const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
        client.connect(err => {
        const collection = client.db("testing").collection("collection1");
        collection.find().toArray((err, result) => {
        if(err) {
        throw err;
        }
        console.log(result);
        })
        });
        client.close();
    • Some concepts
      • Collection: a collection in MongoDb is equivalent to a table in RDBMS, mongoDB has flexible Schema, so documents in one collection do not need to have the same set of fields and the data type for a field can differ
      • Document: MongoDB stores data records as BSON documents. BSON is a binary representation of JSON documents, though it contains more data types than JSON
      • Schema: a document schema is a JSON object that allows you to define the shape and content of documents and embedded documents in a collection

Lesson 16 2021/11/08

  1. mongoose
    • mongoose is an elegant mongodb object modeling for node.js
    • Define a Schema
      • Permitted types in a schema: String, Number, Date, Buffer, Boolean, Mixed, ObjectId, Array, Decimal128, Map
      • By default, mongoose adds an _id property to the schema
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        import mongoose from "mongoose";
        const Schema = mongoose.Schema;

        const userSchema = new Schema({
        name: String,
        email: String,
        });

        const User = mongoose.model("User", userSchema);

        module.exports = User;
    • Create a model
      • You need to convert a schema into a model. Models are constructors compiled from schema definitions. An instance of a model is a document
      • Create a model: const User = mongoose.model("User", userSchema)
    • Queries
      • Model.find()
      • Model.findOne()
      • Model.updateOne()
      • Model.updateMany()
      • Model.deleteOne()
      • Model.deleteMany()
      • query.then()
    • Connections: mongoose.connect(uriString)

Lesson 17 2021/11/10

  1. Heroku
    • Installation
      • Download installer
      • Or run npm install -g heroku
      • Check heroku version: heroku --version

Lesson 18 2021/11/15

Lesson 19 2021/11/17

  1. Introduction to React
    • Test
    • Lesson 20 2021/11/22