Named and default import / exports

šŸ“” What you will learn

  • Importing and Exporting JavaScript code accross files
  • Folder structure to organize your React Native project

šŸ‘¾ Before we start the exercise

If we rely on the official documentation, React does not define a correct way to organize our files and leaves it to the discretion of the developer.

However using the "colocation" is a nice start (keep files that often change together close to each other).

Naming and Export in a nutshell

If you have a JavaScript background you may know we have multiple ways to import/export functions from files.

export

  1. We can export default
function StarshipCard() {
  ...
}

export default StarshipCard
  1. or we can export directly
export function StarshipCard() {
  ...
}

// <------ no `export default` here
  1. or we can create an index.tsx file with one job: importing/exporting files.
// Create a `./src/components/index.tsx`

import ScreenContainer from "./ScreenContainer";
import Offline from "./Offline";
import Card from "./Card";

export { ScreenContainer, Offline, Card };

import

From the another component, to import the files

// with `export default Card`
import Card from "./components/Card";

// with export function Card() { ... }
// with exported index.tsx
import { Card } from "./components/Card";

Named Function Vs. Arrow Function

// We have 2 ways to write our components

const Card = () => {
  ...
}

// or

function Card(){
  ...
}

There are some differences between the 2 solutions but it's not important. For now, choose a solution and keep it concistent accross your stack.

One more thing

There is a nice pattern to know: renaming a component on the go

// App.tsx

import { LoginScreen as App } from "./src/screens/LoginScreen";
export default App;

I agreed with Lloyd Atkinson, and consider default exports in JavaScript modules are a bad idea. As a recap remember:

  1. The syntax for importing a default export is different from the syntax for importing named exports.
  2. Default exports can only be a single value, whereas named exports can be multiple values. This can make it more difficult to structure and organize code when using default exports.
  3. Default exports can make it harder to understand the dependencies of a module, as the imported value is not explicitly named.
  4. It can be difficult to refactor code that uses default exports, as any imported values that depend on the default export must also be updated.

šŸ‘Øā€šŸš€ Exercise 5

Organise your files in a good way. Here is an example using colocation:

.
ā”œā”€ā”€ App.tsx
ā”œā”€ā”€ app.json
ā”œā”€ā”€ assets
│    ā”œā”€ā”€ adaptive-icon.png
│    ā”œā”€ā”€ favicon.png
│    ā”œā”€ā”€ icon.png
│    └── splash.png
ā”œā”€ā”€ babel.config.js
ā”œā”€ā”€ package.json
ā”œā”€ā”€ src
│    ā”œā”€ā”€ components
│    │    ā”œā”€ā”€ ScreenContainer.tsx
│    │    ā”œā”€ā”€ Offline.tsx
│    │    └── Card.tsx
│    └── screens
│          ā”œā”€ā”€ LoginScreen.tsx
│          ā”œā”€ā”€ TermsScreen.tsx
│          └── StarshipFeedScreen.tsx
ā”œā”€ā”€ tsconfig.json
└── yarn.lock
  • Create a ./src/screens/ folder and move all your components here like in the example
  • Create a ./src/components/ folder and move all your components here like in the example

šŸ‘½ Bonus

Because ../../../freakingSucks/

Use Case

import { ScreenContainer } from "../../components/ScreenContainer";

is horrible at scale.

Instead we should be able to:

import { ScreenContainer } from "~/components/ScreenContainer";
  • Open your tsconfig.json file and add:
{
  "extends": "expo/tsconfig.base",
  "compilerOptions": {
    "strict": true,
++    "baseUrl": "./",
++    "paths": {
++      "~/*": ["src/*"]
++    }
  }
}
  • install babel-plugin-root-import with
npm install babel-plugin-root-import
  • Open your babel.config.js file and add plugins array section:
  return {
    presets: ['babel-preset-expo'],
    plugins: [
      [
        "babel-plugin-root-import",
        {
          rootPathPrefix: "~/",
          rootPathSuffix: "./src/",
        },
      ],
    ],
  };