Grokking React Native
Vote

0% completed

​

Importing and Exporting Components

Default Export

Importing a Default Export

The import path

Named Export

Importing a Named Export

Common Mistakes

Forgetting to export

Curly braces around a default export

No curly braces around a named export

A wrong path

How does code in one file use a component that was written in another file? The file that owns the component marks it as available, which is called exporting it. The file that needs the component then asks for it by path, which is called importing it. Each file in a project is closed to the others until you connect them in this way.

Apps are divided like this because a single file containing every component would be hard to read, debug and extend. With separate files, each one is responsible for one part of the app.

MainApp.js imports three components by path, and each one lives in a file of its own that exports it.
MainApp.js imports three components by path, and each one lives in a file of its own that exports it.

The picture shows the arrangement: a main file that uses three components, each of which lives in a file of its own. Follow an arrow from an import line in MainApp.js to the file that exports that component. The rest of this lesson explains each form.

Separate files help in four ways. The project is easier to navigate, because each file has one purpose. A component can be used across the app without being rewritten. A problem is easier to find, because you can look at one component at a time. Finally, people on a team can work on different components with fewer conflicting edits.

Default Export

You have already seen export default at the end of the examples in this course. It marks one thing in a file as the main thing that the file provides. Create a file named Greeting.js:

import { Text } from 'react-native'; const Greeting = () => { return <Text>Hello, welcome to our app!</Text>; }; export default Greeting;

A file can have only one default export. Some code writes the export in the same line as the function, as in export default function Greeting() { ... }, which has the same effect.

Importing a Default Export

A second file, HomeScreen.js, in the same folder can now use it:

import { View } from 'react-native'; import Greeting from './Greeting'; const HomeScreen = () => { return ( <View> <Greeting /> </View> ); }; export default HomeScreen;

No curly braces appear around Greeting, because the import asks for the default export of the file. For the same reason, you choose the local name. import Welcome from './Greeting'; followed by <Welcome /> rendered the same text in our test.

The screen does not change until the app reaches this code, because App.js is still the root component. To see the result on your device, import HomeScreen in App.js in the same way and return <HomeScreen /> from its function.

The import path

The path after from starts at the folder of the file that contains the import, and the .js extension is left out. Suppose a project looks like this:

App.js Greeting.js components/ Header.js screens/ HomeScreen.js

Three cases cover nearly everything you will write:

  • From App.js to a file in the same folder, use ./ and the name: ./Greeting.
  • From App.js to a file in a subfolder, include the folder: ./components/Header.
  • From screens/HomeScreen.js to a file outside its folder, use ../ to go up one level: ../components/Header.

Named Export

A named export lets a file provide several things under their own names. Create a file named Messages.js:

import { Text } from 'react-native'; const Greeting = () => { return <Text>Hello, welcome to our app!</Text>; }; const Farewell = () => { return <Text>Goodbye, see you again!</Text>; }; export { Greeting, Farewell };

You can also write the word export directly in front of each declaration, as in export const Farewell = () => { ... };. The result is the same.

Importing a Named Export

Curly braces ask for exports by their exact names:

import { View } from 'react-native'; import { Greeting, Farewell } from './Messages'; const HomeScreen = () => { return ( <View> <Greeting /> <Farewell /> </View> ); }; export default HomeScreen;

The name must match the export. If you need a different local name, rename it with as, as in import { Greeting as Welcome } from './Messages';.

One file can have both kinds at once, and one import line can ask for both. With a file that contains export default function Greeting and export const Farewell, the import is import Greeting, { Farewell } from './Both';.

Each export form in a file matches one import form in the other file: no braces for the default, and braces with the exact name for a named export.
Each export form in a file matches one import form in the other file: no braces for the default, and braces with the exact name for a named export.

The diagram pairs each export with its import. The presence of braces in the import depends only on how the other file exported the component.

Default exportNamed export
How many in a fileOneAny number
Exportexport default Greeting;export { Greeting, Farewell };
Importimport Greeting from './Greeting';import { Greeting } from './Messages';
Curly bracesNoYes
Local nameYou choose itThe exported name, or as to rename

A common convention is to use a default export when a file contains one component, and named exports when it contains several. Both forms work the same way at run time, so this is a matter of keeping a project consistent.

Common Mistakes

All of the next three mistakes end in the same error, because in each case the import finds nothing to use. We ran each one, and React reported the following message. The word after but got: was undefined for the second and third mistakes, and object for the first:

Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. Check the render method of `HomeScreen`.

When you see this message, check the import lines of the component that it names.

Forgetting to export

The file defines Greeting but never makes it available:

import { Text } from 'react-native'; const Greeting = () => { return <Text>Hello!</Text>; };

Add the missing line at the end of the file:

export default Greeting;

Curly braces around a default export

Greeting.js has a default export, so this line asks for a name that the file does not export:

import { Greeting } from './Greeting';

The braces must go:

import Greeting from './Greeting';

No curly braces around a named export

Messages.js has only named exports, so this line asks for a default export that does not exist:

import Greeting from './Messages';

The braces must be added:

import { Greeting } from './Messages';

A wrong path

A path that points to no file fails in a different way. The app does not start, and the bundler reports that it cannot resolve the module. Compare the path with the three cases above, and check the spelling and the capital letters of the file name.

Reading Progress

0%


Vote for new content

On This Page

Default Export

Importing a Default Export

The import path

Named Export

Importing a Named Export

Common Mistakes

Forgetting to export

Curly braces around a default export

No curly braces around a named export

A wrong path