React Native + Expo Go Week 7

Week 10 of documenting my app development learning journey (June 28 - August 3)

A Look Outside My Network:

Apple released iOS 26 Beta 4 introducing AI-powered news summaries along with upgrading the user’s experience in terms of UI and design. Maybe I’ll look at that if I choose to specialize in one mobile environment one day, but i do have an iPhone, so I’m curious as to see how these new UI features will work!

This Week’s Goal:

Get through the new tutorial.

What I Did Last Week:

I followed a pretty outdated tutorial (by Mosh), and thus eventually failed after hitting a speed bump, so I had to find a new tutorial that would be more updated. However, I still managed to launch my own React Native App on my iPhone vis Metro Bundler.

Hey, I’m back, albeit pretty tired from the net 20 hours of sleep I got from last week total.

July 28th, 2025

I found this cool other tutorial yesterday: https://www.youtube.com/watch?v=J50gwzwLvAk&t=12s

So far, it’s going well; I already learned how the structure of a blank React Native template works, and how the syntax works.

Essentially, every file within the .\app folder has control over its corresponding page/screen. index.tsx will ideally be the first file to run, like an __init__ method in Python. Meanwhile, _layout.tsx is where the file-based routing is managed.

Later, I would learn that in _layout.tsx, there are different ways to “organize” how links to other pages (files) would be shown, such as…

  1. <Stack>: Places links to other pages in a linear fashion (e.g., page1 → page2 → page3) and auto-creates a “back” button on the top-left of the screen, so you can be sure of where you just came from and go back.

  2. <Tabs>: Organizes links to other pages (paired with icons) on the bottom of the screen, a common layout format in popular social media platforms. This layout can’t “memorize” which page you were at last.

Here’s an example of a _layout.tsx file that uses <Tabs>:

import Entypo from '@expo/vector-icons/Entypo'; import Feather from '@expo/vector-icons/Feather'; import { Tabs } from "expo-router"; export default function TabsLayout() { return ( () }}/> () }}/> ); }

Electronic Etiquette

By the way, parentheses “()” surround the name of the folder when creating organizational/layout folders, to mark that they are for organization/layouts (e.g., (tabs)).

I also learned that icons are really important in mobile apps, to maintain consistency and design, so using this website, I managed to get some icons to customize my own app. All of the possible icons that can be imported aren’t from a singular
library” per se, but from multiple like “Feather”, “AntDesign”, “MaterialIcons”, “SimpleLineIcons”, etc. (Ooooh! There’s also FontAwesome, which is known for providing free icons for web development too!)

Oh, Expo itself has a tutorial too, cool. https://docs.expo.dev/tutorial/ (I didn’t do this but I did use it for reference in some parts of my app)

It’s a React Thing: Components, Properties, and Children

Elements are used but usually aren’t explicitly defined in React due to their simplicity: more prominently, there are components. A component in React is a self-contained, reusable piece of code that defines a specific part of the user interface (UI), and a component itself would produce elements without the element explicitly being defined.

<component>Text</component>

Components can also double-up as functions, but for React to recognize a function as a component, the function name must be in PascalCase, otherwise known as UpperCamelCase. When defining a “function component“, as they’re called, they can be defined through normal JS function definition (regular or arrow).

function MyComponent( ... ) { ... } OR const MyComponent = () => {}

Within a component, there are properties, which are structured like key-value pairs (like dictionaries, for you Python folks). If the component is a function component, properties are very similar to parameters in how properties are passed in as parameters in the component’s corresponding function.

The children are a special type of prop that is everything that are between the two tags of the component.

That being said, when a function component is used in code, that function is called, using its properties (or props) and children by default.

July 29th, 2025

Today, I learned how to make an icon change if it’s selected or not; using the tabBarIcon option object and the focused variable that comes from that object, I made the icon for the Login page responsive to whether it was “focused” on or not.

<Tabs.Screen name="login" options={{ 
              title: "Login",
              tabBarIcon: (
                { focused }
              ) => {
                return focused ? (
                  <FontAwesome6 name="door-open" size={24} color="black" />
                ) : (
                  <FontAwesome6 name="door-closed" size={24} color="black" />
                )
              }
        }}/>

I also learned about backend databases today, and how they’re essential to app development, because they facilitate things related to data processing, storage, and security. The tutorial recommended that I use AppWrite. This is a relational database, which means that it uses tables made up of rows and columns to organize data, where the data points are related to each other through connections.

I then created a \lib folder in which I stored the file appwrite.ts, which will be the configuration file for connecting AppWrite to my project. After, I installed the React Native App Software Development Kit (SDK) to do so.

Next, I created I set my Client endpoint and project names/ids in my code, and created my platform on the AppWrite website.

Electronic Etiquette

Environment Variables (or just env) are usually all-caps. For example: PROJECT_ID

The “Package name” can be anything you want, supposedly; just follow the syntax that they suggest.

After, I created a env.local file that stored the IDs and names required for setting up the connection to the backend.

From that, I combined the endpoint, project ID, and the platform to create a new Client object. I was able to do this because I had installed react-native-appwrite (via npm) before, and from that library, I used its Client object.

import { Account, Client, Databases } from "react-native-appwrite";

export const client = new Client()
    .setEndpoint(process.env.EXPO_PUBLIC_APPWRITE_ENDPOINT!)
    .setProject(process.env.EXPO_PUBLIC_APPWRITE_PROJECT_ID!)
    .setPlatform(process.env.EXPO_PUBLIC_APPWRITE_PLATFORM!);
// The "!" are there so that we tell the computer that we know for sure there there is a value stored in those env variables.

export const account = new Account(client);

With this new backend connected, I can not create a login system using authentication and everything, so I made an auth.tsx page, where I learned how to create a more responsive UI with a new tag, <KeyboardAvoidingView> and using its behavior property (prop) to adapt to different mobile environments (i.e., Apple vs Android).

<KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : "height"}>
  <View>
    ...
  </View>
</KeyboardAvoidingView>

After that, I followed to tutorial to make the signing up process to be more responsive in separating the “Log In” vs “Create An Account?” screens using the useState function from react, I initialized two variables that would help the app see recognize if the user was a new user or a returning one:

const [isSignUp, setIsSignUp] = useState<boolean>(false);
// This is how variables work in tsreact, pretty complicated

When you’re listing options or property (prop)s within a tag, DON’T use commas.

Also, given the new log in/create account page that I’m making, the tutorial also taught me how to use the useRouter() hook and use children to “redirect” users who don’t have an account/haven’t signed in to go to that page.

Learning about how the useEffect hook was a long process, because of its versatility. Long story short, it’s like a “speedbump” in React Native rendering. Processes within the app that don’t have to do with displaying the UI are called side effects (like fetching data from an API) and they take time to complete. Using this hook helps React delay running these side effects until after the UI has finished rendering, therefore regulating the flow of data and “stabilizing” the app.

function RouteGuard({ children } : { children: React.ReactNode }) {

  const router = useRouter();
  const isAuth = false;

  useEffect(() => {
    if (!isAuth) {
      router.replace("/auth");
    }
  });

  return <>{children}</>
}

...

export default function RootLayout() {
  return (
    <RouteGuard>
      ...
    </RouteGuard>
  );
}

It’s a React Thing: Hooks and Fragments

A Hook in React is a special JavaScript function that lets you "hook into" React features (like state and lifecycle events) while using function components. Hooks allow function components to do things that previously only class components could do, such as remembering data (state) or running code when the component appears or changes.

Meanwhile, fragments look like this:

<> … </>

…and are used to “wrap” a whole group of things, in this case all the different { children }, and has the program treat the group as one thing.

Here’s an explanation of how children work in this scenario (since I don’t really know myself :/)

Inside RouteGuard, you receive this as a parameter (often by destructuring {children}) and can render it wherever you want, usually just by returning {children} in your JSX. This way, RouteGuard acts as a wrapper that controls whether the nested UI (the children) should be rendered (for example, if authorization checks pass) or not.

Key points about how children works here:

children is the nested content inside <RouteGuard>...</RouteGuard>.

It's passed automatically by React as a prop (property).

Think of children as just a placeholder for whatever JSX you place inside the component.

The wrapped content (children) is rendered inside the guard if conditions are met, otherwise, the guard can redirect or return something else.

children itself is not a method or special function—just React components grouped together.

This pattern is widely used for creating reusable wrappers or guards that can contain any arbitrary UI, with the guard managing whether to show or block that UI based on logic like authentication.

To summarize explicitly for your snippet:

The <Stack>...</Stack> JSX is the children.

RouteGuard receives this as a prop (property) and renders <>{children}</> (a React Fragment with the children inside).

This mechanism lets RouteGuard be a reusable "gatekeeper" component that conditionally renders the nested components passed as children.

-perplexity.ai

Oh, thanks perplexity.

July 31th, 2025

I learned that there are several ways in how one can store a data point or variable. What do I mean by that? A variable can be stored in…

  • A state via useState: States can update the UI when their values are changed, but can be computationally expensive.

  • A reference via useRef: References are good for when you want to just store a value across renders (when React updates the UI) but do not need to trigger rendering when their values are changed.

  • A regular variable via let or const: Since regular variables will be “erased” after the next render, these should only be used within functions for instantaneous calculations.

Within creating an app, several variables with numerous different data types could be being thrown around the app, and it’s important to make sure that each variable is its correct type before using it to go through with an operation, whether that be a refresh or whatever. This is the reason why type exists. It’s not a class, but it’s more of like a “checklist” or “criteria” for a type of variable that holds more than one data type, for instance, authentication contexts.

For example, in this code, this type ensures that and variable of type AuthContextType will have two strings that will be categorized under “signUp”, and another two categorized under “signIn”, all of which will be derived from Promise requests.

// In auth-context.tsx
type AuthContextType = {
    user: Models.User<Models.Preferences> | null;
    signUp: (email: string, password: string) => Promise<string | null>;
    signIn: (email: string, password: string) => Promise<string | null>;
}

Anyways, I continued learning how the backend of my app works:

  1. After I got my backend connected (from two days ago), I then used the client object that I created to initialize an instance of the Account class called account.

// In appwrite.ts
    ...
    .setPlatform(process.env.EXPO_PUBLIC_APPWRITE_PLATFORM!);

export const account = new Account(client);
  1. Next, within a function called signUp, I utilized the account object to create accounts, using the await keyword to ensure that the execution is paused until the email and password are retrieved (or it’s verified that they cannot be retrieved), and signs the user in after.

    However, if there is an invalid email format, wrong password, or any other error, then the app will return the error message.

// In auth-context.tsx
export function AuthProvider({children} : {children: React.ReactNode}) {
    const signUp = async (email: string, password: string) => {
        try {
            await account.create(ID.unique(), email, password);
            // Signing up automatically does signing in
            await signIn(email, password);
            return null;
        } catch(error) {
            if (error instanceof Error) {
                return error.message;
            }
            return "An error occurred.";
        }
    };
    ...
  1. I created similar functionality but for a signIn function instead, which utilized await account.createEmailPasswordSession(email, password); 

  2. At the end of AuthProvider, I made it return the { children } (aka all the elements that are within the <AuthProvider> tag) within the AuthContext.Provider wrapping the { children }, which enables the { children } to access the signUp and signIn functions.

    ...
    return <AuthContext.Provider value={{ signUp, signIn }}>
                { children }
            </AuthContext.Provider>
}

Right after, a AuthContext instance is initialized (named AuthContext), and it is assigned the return value of the react library’s createContext function. In this case, the createContext creates a new context that either holds an AuthContextType or is a undefined type. By default, it starts off as undefined as its default value; hence, that’s why it’s set as the function’s parameter.

const AuthContext = createContext<AuthContextType | undefined>(undefined);

AuthContext commonly denotes a construct that manages or represents the authentication state, flow, or security policies relevant to user identity and access control, with its exact implementation varying by platform or framework.

-perplexity,ai, 2025

Now, I just was tired from all this backend stuff, so I decided to give my app a go:

wtf

August 1st, 2025

Well, well, well. So the reason I couldn’t test my app (after I tried to debug with ChatGPT for a few hours) was because there was this function: RouteGuard that would automatically reroute me (the user) to the /auth page, but that would create an infinite loop, because I haven’t gotten to the point the the tutorial where PedroTech corrected his mistake.

function RouteGuard({ children } : { children: React.ReactNode }) {

  const router = useRouter();
  const isAuth = false; // This line

  useEffect(() => {
    if (!isAuth) {
      router.replace("/auth");
    }
  }, [isAuth, router]);

  return <>{children}</>
}

BUT! I noticed that the tutorial was moving on through even though that error was there, so how did the tutorial still manage to display the emulator while moving throughout this “hidden” broken functionality? Well, it was because the tutorial never rebuilt the app ever since the initial creation of the app, whereas I rebuilt the app in the middle of the tutorial to get it rendering on my iPhone (and through a Pixel 9a emulator through Android Studio).

So after creating a getUser function and implementing the “if you don’t have an account or are not signed in you go the /auth page” functionality, I kept on moving through the tutorial.

Special Thanks:

To Pedro from this video—thanks for the guidance and help, yo!

Also thanks to my mom who took the time to look at my progress on my app (via my iPhone).