Importing and Exporting Components
Overview¶
The magic of components lies in their reusability: you can create components that are composed of other components. But as you nest more and more components, it often makes sense to start splitting them into different files. This lets you keep your files easy to scan and reuse components in more places.
You will learn
- What a root component module is
- How to import a component from another file
- How ReactPy expresses "private" and "public" components
- How to import and export multiple components from one file
- How to split components into multiple files
The root component module¶
In Your First Component, you made a profile component and a gallery component that renders it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
1 2 3 4 | |
These currently live in a single module. Whichever module holds the component you hand to an executor is your root component module — the ASGI executor in Creating a Standalone React App takes that component directly:
from reactpy.executors.asgi import ReactPy
from app import gallery
my_app = ReactPy(gallery)
Which module plays this role depends on your executor. The middleware executor takes dotted paths instead, e.g. ["my_components.hello_world"], and the CSR executor takes a path to a file whose root component it mounts.
Exporting and importing a component¶
What if you want to change the landing screen in the future and put a list of science books there? Or place all the profiles somewhere else? It makes sense to move gallery and profile into their own module. This makes them more modular and reusable in other files. You can move a component in three steps:
- Make a new Python file to put the components in.
- Define your component functions in that file. Unlike JavaScript, Python has no
exportkeyword — every name defined at module level is importable. - Import it in the module where you'll use the component.
Here both profile and gallery have moved into a new file called gallery.py. Now app.py imports gallery from it:
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Notice how this example is broken down into two component files now:
gallery.py:- Defines the
_profilecomponent, which is only used within the same file and is kept private. - Makes
gallerythe public component of the module.
- Defines the
app.py:- Imports
galleryfromgallery.py. - Defines the root
appcomponent.
- Imports
Note
ReactPy does not care which module a component is defined in, so unlike ReactJS there is no distinction between "default" and "named" exports. from gallery import gallery, profile and two separate import statements mean the same thing.
Public and private components¶
ReactJS lets you keep a component unexported so that only its own file can use it. Python has no equivalent enforcement, but it has two widely respected conventions that express the same intent.
A leading underscore marks a name as private to its module:
@component
def _profile():
...
And __all__ lists the names a module publishes. It is what a star import exports, and what linters and type checkers read to decide what is public API:
__all__ = ["gallery"]
This is why _profile is both underscore-prefixed and absent from __all__ in the example above.
Pitfall
These conventions are advisory, not enforced. from gallery import _profile still works, because Python has no private keyword. Do not reach for underscore-prefixed names from another module, and do not rely on them being unavailable — treat a broken convention as a bug in the importing code, not as protection.
Deep Dive
Naming modules and components¶
Because imports name modules rather than files, give both meaningful names. scientists.py defining gallery and _profile reads better than utils.py defining Gallery, and it also keeps you consistent with the rest of the docs, which write components in snake_case.
Components should still be called everywhere they are used, so a component used by two modules must be imported in both of them. There is no global component registry to fall back on.
Exporting and importing multiple components from the same file¶
What if you want to show just one profile instead of a gallery? Then app.py needs profile too. Add it to the module's __all__ and import it by name:
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Now gallery.py publishes both components:
gallery.py:- Lists
galleryandprofilein__all__.
- Lists
app.py:- Imports both
galleryandprofilefromgallery.py. - Renders each of them.
- Imports both
Recap¶
You've learned:
- What a root component module is, and that it depends on your executor
- How to import a component from another file
- How ReactPy expresses public and private components with
__all__and a leading underscore - How to export multiple components from the same file
Next Steps¶
Now that your components can live in separate files, continue to Passing Props to a Component to make them configurable.