Skip to content

pachun/Pep

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

This project is deprecated

Expo's gotten better at making it easy to create new projects with this stuff configured.

I'd start with

npx create-expo-app@latest --template blank-typescript

Then check out their using eslint and prettier docs and well as their manual installation steps for adding expo-router.


Pep

Begin your new expo app projects with some pep; that is, including:

Here is also a blog post with more about the motivation for creating pep.

Getting Started

gem install pep
pep my-app-name # this will take a minute and you'll see yarn output
cd my-app-name
yarn start

Now, edit your src/App.tsx file.

Defaults

Prettier, typescript, eslint, and react navigation are all added to your project and set up in discrete commits; The way you'd do it by hand if you spent the extra time.

The best way to inspect the changes pep makes to a default Expo project is by creating a new project with pep and inspecting the project's git log.

Here is an example of what a project-created-with-pep's git log looks like (excluding the last commit which adds a readme to that project).

We'll cover other ways to peek ahead and inspect the default configurations ahead of time, if that's your thing 😉

Prettier

You can view all the changes pep makes to add prettier to a default Expo project here.

You can view the default prettier configuration here.

Once you've created a project with pep, you can view or edit the prettier configuration by opening the hidden dotfile named .prettierrc

Eslint

You can view all the changes pep makes to add eslint to a default Expo project here.

You can view the default eslint configuration here.

Once you've created a project with pep, you can view or edit the eslint configuration by opening the hidden dotfile named .eslintrc.js

Typescript

You can view all the changes pep makes to configure typescript in a default Expo project here.

You can view the default changes made to expo's default typescript configuration here.

Once you've created a project with pep, you can view or edit the tyepscript configuration by opening the file named tsconfig.json

The default expo tsconfig.json combined with pep's changes (which are discussed in detail in Expo's docs here) generates the following tsconfig.json content:

{
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true,
    "allowJs": true,
    "esModuleInterop": true,
    "jsx": "react-native",
    "lib": ["DOM", "ESNext"],
    "moduleResolution": "node",
    "noEmit": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "target": "ESNext"
  }
}

Absolute Imports

You can view all the changes pep makes to add absolute imports to a default Expo project here.

Once a new project is created with pep, you can always import code relative to the src/ directory.

... For Example ...

If you are importing the component in src/components/FancyTextInput.tsx from src/screens/HomeScreen.tsx, you can do so like this:

import FancyTextInput from "components/FancyTextInput";

... Rather than doing it like this ...

import FancyTextInput from "../components/FancyTextInput";

I've found this setting enables easier refactoring when copying and pasting import lines, and especially when moving files around.

The best way to view the changes that go into making this feature work is to inspect the commit titled "Set /src as the root directory for app code" after creating a new pep project.

The setup for this feature touches several configuration files, including: .eslintrc.js, babel.config.js, and tsconfig.json.

You can skim through this class to get an idea of what exactly gets changed before creating a new project with pep.

React Navigation

You can view all the changes pep makes to add React Navigation to a default Expo project here.

Your default src/App.tsx file will look like this after setting up a new pep project:

import { Button, Text, TextInput, View } from "react-native"
import { DefaultTheme, NavigationContainer } from "@react-navigation/native"
import { createNativeStackNavigator } from "@react-navigation/native-stack"
import type { NativeStackScreenProps } from "@react-navigation/native-stack"
import { useState } from "react"

type StackNavigatorParams = {
  Home: undefined
  Details: { homeScreensTextInputValue: string }
}

type HomeProps = NativeStackScreenProps<StackNavigatorParams, "Home">
type DetailsProps = NativeStackScreenProps<StackNavigatorParams, "Details">

const HomeScreen = ({ navigation }: HomeProps): React.ReactElement => {
  const [homeScreensTextInputValue, setHomescreensTextInputValue] =
    useState<string>("")
  return (
    <View style={{ flex: 1, alignItems: "center" }}>
      <Text style={{ fontWeight: "bold", marginTop: 100 }}>
        Open `src/App.tsx` to begin editing your app.
      </Text>
      <Text style={{ marginTop: 100 }}>Home Screen</Text>
      <TextInput
        value={homeScreensTextInputValue}
        onChangeText={setHomescreensTextInputValue}
        placeholder="Type something here to see it on the details screen"
        style={{
          width: "90%",
          height: 30,
          textAlign: "center",
          borderWidth: 1,
          borderColor: "#aaa",
          marginTop: 20,
          marginBottom: 20,
        }}
      />
      <Button
        title="Go to Details Screen"
        onPress={(): void => {
          navigation.navigate("Details", { homeScreensTextInputValue })
        }}
      />
    </View>
  )
}

const DetailsScreen = ({ route }: DetailsProps): React.ReactElement => {
  const { homeScreensTextInputValue } = route.params
  return (
    <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
      <Text>Details Screen says: {homeScreensTextInputValue}</Text>
    </View>
  )
}

const Stack = createNativeStackNavigator<StackNavigatorParams>()

const MyTheme = {
  ...DefaultTheme,
  colors: {
    ...DefaultTheme.colors,
    background: "#fff",
  },
}

const App = (): React.ReactElement => (
  <NavigationContainer theme={MyTheme}>
    <Stack.Navigator>
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
  </NavigationContainer>
)

export default App

Something I really value about this setup (in addition to it setting up react navigation) is the effort that goes into making clear how to use react navigation in a way that makes typescript happy; eg everything which uses this type definition:

type StackNavigatorParams = {
  Home: undefined;
  Details: { homeScreensTextInputValue: string };
};

Which includes the creation of the stack navigator ...

const Stack = createNativeStackNavigator<StackNavigatorParams>();

... As well as the creation of a type for the top level screens's component props ...

import type { NativeStackScreenProps } from "@react-navigation/native-stack"

// ...

type HomeProps = NativeStackScreenProps<StackNavigatorParams, "Home">
type DetailsProps = NativeStackScreenProps<StackNavigatorParams, "Details">

const HomeScreen = ({ navigation }: HomeProps): React.ReactElement => {
  // ...
  return (
    // ...
    <Button
      title="Go to Details Screen"
      onPress={(): void => {
        navigation.navigate("Details", { homeScreensTextInputValue })
      }}
    />
    // ...
  )
}

const DetailsScreen = ({ route }: DetailsProps): React.ReactElement => {
  const { homeScreensTextInputValue } = route.params
  return (
    <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
      <Text>Details Screen says: {homeScreensTextInputValue}</Text>
    </View>
  )
}

... Which is needed to tell typescript where the navigation and route props come from, as well as which route params each screen expects passed to it, like above with the line ...

const { homeScreensTextInputValue } = route.params

Every time I go to setup React Navigation, it's been long enough since the last time that I did it that I have to go back and re-read the docs over here.

Pep also creates a custom React Navigation theme and applies it:

import { DefaultTheme } from "@react-navigation/native"

const MyTheme = {
  ...DefaultTheme,
  colors: {
    ...DefaultTheme.colors,
    background: "#fff",
  },
}

const App = (): React.ReactElement => (
  <NavigationContainer theme={MyTheme}>
    // ...
  </NavigationContainer>
)

The only thing which pep actually changes here is the default screen background colors, which it sets to white because React Navigation defaults screen background colors to a slightly off-gray color which I find myself also consistently looking back in the docs for how to switch that back to white.

💃

I hope this peppy little automation saves you some time, too!

About

Expo app scaffolding

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages