Creating a New Application page
Generate a new React Native application using the CLI.
Overview
In this section, you will:
- Use the React Native CLI to generate a new React Native application.
- Test code with React Testing Library.
- Add code quality tools.
Objective 1: Generate the “Place My Order” application
Create a new React Native application named “Place My Order” that supports TypeScript and can be emulated and tested.
Using the React Native CLI
React Native has a built-in command line interface.
Rather than install and manage a specific version of the CLI globally, we recommend you access the current version at runtime using npx
, which ships as part of npm.
With npx react-native <command>
, the current stable version of the CLI will be downloaded and executed at the time the command is run.
Setup 1
✏️ Open a terminal and move to a location where you want to generate your React application, then execute the following command:
npx react-native@0.74.1 init PlaceMyOrder --version 0.74.1
The command runs npx
, using react-native
to create a new React Native application named "PlaceMyOrder with TypeScript support.
✏️ Now cd
into the new directory created for the application:
cd PlaceMyOrder
When cloning a project from a git repository, it will also be necessary to run npm install
in the directory, but the app setup has done this for us already.
Verify 1
Once you have completed the previous step you will be able to start the development server and see the default welcome page.
The development server is a useful tool. When it starts, it transpiles the TypeScript and JSX code into JavaScript and bundles it for delivery to the device. It also watches for changes to the source code, and when they occur, it repeats the process, then causes the device to reload with those changes.
✏️ Start the virtual device you created in the previous module.
✏️ Run the command:
npm run start
✏️ Press the a
key to run the app on the open Android virtual device.
The first time you run it for a given target will take significantly longer than subsequent runs. Once open, you should see the default "Welcome to React Native" screen.
Objective 2: Add testing infrastructure
Testing code with React Testing Library
We will create unit tests for our application using the React Native Testing Library. The unit tests for components will be focused on verifying that a component creates the correct output based on the state the component is provided. We also need to create tests for any React custom Hooks we create to ensure they provide the expected results.
Setup 2
✏️ Install the new dev dependencies:
npm install --save-dev @testing-library/react-native@12 @types/jest@29
✏️ Create jest-setup.ts and update it to be:
import '@testing-library/react-native/extend-expect';
✏️ Update jest.config.js to be:
module.exports = {
preset: 'react-native',
setupFilesAfterEnv: ['<rootDir>/jest-setup.ts'],
};
✏️ Delete the unneeded generated folder __tests__
.
✏️ Create App.test.tsx and update it to be:
import {render, screen} from '@testing-library/react-native';
import App from './App';
describe('App', () => {
it('renders', async () => {
render(<App />);
expect(screen.getByText(/Place my order/i)).toBeOnTheScreen();
});
});
✏️ Update App.tsx to be:
import {Text} from 'react-native';
const App: React.FC = () => {
return (
<Text>Place My Order: Coming Soon!</Text>
);
}
export default App;
Verify 2
After completing the previous steps you will be able to run unit tests. Execute the command:
npm run test
and "Test Suites: 1 passed, 1 total" will be written to the console.
Objective 3: Clean up the generated code and add helpers
Before we begin adding any content, it’s a good idea to clean up generated files and add code quality tools.
Setup 3
✏️ Install the new dev dependencies:
npm install --save-dev @bitovi/eslint-config@1 depcheck@1
✏️ Create .depcheckrc and update it to be:
ignores:
- "@types/*"
- "@babel/*"
- "babel-*"
- "*-babel"
- "@react-native/eslint-config"
- identity-obj-proxy
- react-native-dotenv
✏️ Update .eslintrc.js to be:
module.exports = {
root: true,
extends: "@bitovi/eslint-config/react",
settings: {
"import/ignore": ["react-native/*"],
},
rules: {
"@typescript-eslint/consistent-type-imports": [
"error",
{
prefer: "no-type-imports",
fixStyle: "inline-type-imports",
},
],
},
}
✏️ Update .gitignore to be:
# OSX
#
.DS_Store
# Windows
#
Thumbs.db
# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
**/.xcode.env.local
# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml
*.hprof
.cxx/
*.keystore
!debug.keystore
# node.js
#
node_modules/
npm-debug.log
yarn-error.log
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/
**/fastlane/report.xml
**/fastlane/Preview.html
**/fastlane/screenshots
**/fastlane/test_output
# Bundle artifact
*.jsbundle
*.tsbuildinfo
# Ruby / CocoaPods
**/Pods/
/vendor/bundle/
# Temporary files created by Metro to check the health of the file watcher
.metro-health-check*
# testing
/coverage
# Yarn
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
✏️ Update .prettierrc.js to be:
module.exports = {
endOfLine: "auto",
semi: false,
trailingComma: "all",
}
✏️ Update metro.config.js to be:
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config")
/**
* Metro configuration
* https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
const config = {}
module.exports = mergeConfig(getDefaultConfig(__dirname), config)
✏️ Update package.json to be:
{
"name": "PlaceMyOrder",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"clean": "rm -rf tsconfig.tsbuildinfo coverage android/.gradle android/build android/app/build node_modules/.cache",
"depcheck": "depcheck .",
"eslint": "eslint .",
"eslint:fix": "eslint --fix .",
"ios": "react-native run-ios",
"lint": "npm run eslint && npm run prettier",
"lint:fix": "npm run eslint:fix && npm run prettier:fix",
"precheck": "npm run typecheck && npm run lint && npm run depcheck && npm test",
"prettier": "prettier --check .",
"prettier:fix": "prettier --write .",
"start": "react-native start --reset-cache",
"test": "jest",
"test:inspect": "node --inspect-brk ./node_modules/.bin/jest --watch",
"test:watch": "jest --watch",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"react": "18.2.0",
"react-native": "0.74.1"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@bitovi/eslint-config": "^1.8.0",
"@react-native/babel-preset": "0.74.83",
"@react-native/eslint-config": "0.74.83",
"@react-native/metro-config": "0.74.83",
"@react-native/typescript-config": "0.74.83",
"@testing-library/react-native": "^12.5.0",
"@types/jest": "^29.5.12",
"@types/react": "^18.2.6",
"@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.6.3",
"depcheck": "^1.4.7",
"eslint": "^8.19.0",
"jest": "^29.6.3",
"prettier": "2.8.8",
"react-test-renderer": "18.2.0",
"typescript": "5.0.4"
},
"engines": {
"node": ">=20"
}
}
✏️ Update tsconfig.json to be:
{
"extends": "@react-native/typescript-config/tsconfig.json",
"compilerOptions": {
"module": "ES2022",
"types": ["react-native", "jest", "node"],
"declaration": true,
"composite": true,
"incremental": true,
"strict": true,
"noEmit": true,
"allowJs": false,
"allowSyntheticDefaultImports": true,
"downlevelIteration": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"skipLibCheck": true,
"useDefineForClassFields": true
},
"include": ["@types", "*.ts", "*.tsx", "src"],
"exclude": ["node_modules"]
}
✏️ Now that we have prettier and eslint set up, we need to make sure our code is following the new standards. You can apply most of the rules automatically. Run:
npm run lint:fix
Note: If you installed the ESLint and Prettier VS Code plugins and enable "format on save" in the settings, VS Code will make the necessary changes any time you save a file too!
Verify 3
✏️ Run the new code quality scripts.
npm run typecheck
npm run eslint
npm run prettier
npm run depcheck
These scripts should all pass successfully. You can run all of these, and the tests, with
npm run precheck
Next steps
Next, let’s learn about JSX to understand React’s templating language.