So we've been using this keyword import and export for quite a few lessons now,
and I wanted to take a moment to do a quick deep-dive on this concept of modules which comes from ES6,
so that way we can better understand what it is that we're doing when we're importing React from the
react module, and how does it actually work behind the scenes?
So here I've got a very simple starting Project.
So go ahead and open it up and fork your own copy, and all it displays at the moment is just three bullet
points 1, 2 and 3.
Now we've seen in the last lesson that we were able to create custom files which created independent
packaged bits of functionality which then, depending on what it is that we need from it, we can import
the functionality into a different file.
In my case, in my src folder, I'm just going to go ahead and create a new file which I'll call math.js
.
And we're not dealing with React components here,
this is just going to be a simple JavaScript file. In this file
I'm going to create a new const which is going to be pi and I'm going to save the value of pi,
3.1415962.
Now, let's say that we had this file called math.js and it would store the value of pi amongst
other things.
So what if in our index.js we wanted to get hold of the value of pi and display it in our list
item here?
Well, we would have to somehow export this value from this file,
right?
This math.js then becomes a new module, and we can export whatever it is that we want to be used
elsewhere from this file.
So in this case there's only one thing that we could possibly export.
So I'm going to export it as a default,
and then I'm going to specify the thing that I want to export which is the value of this const pi.
And now when I go back to my index.js I can now import pi from that file, "/math.js"
.
So I'll keep the extension there just to make it easier to see in this case.
Now that we've imported pi, we can now use it inside our code and I'm going to replace the content of
my first list item with the value of pi.
So notice what's happened here,
I'm now importing the const pi from our math.js and our math.js specifies a single export
which is the default thing to be exported which is the value of this const.
Now, back over here, when I'm importing something that is the default, I can actually name it whatever
I want. I could call it pi,
and as long as I updated my code to be consistent with the name I've given in the import then it works
just as well. Now what if we had more than one thing in this file math.js?
How would we export multiple things?
Well, in addition to creating a default export which means that when another file writes import something
from this file, that something is going to be equivalent to the default export,
but if you wanted to import more than one thing, then you can write another export statement with a set
of curly braces,
and inside these curly braces you can define all of the non-default exports,
so what else do you want to export from this file.
So maybe let's add the doublePi and triplePi functions in addition to the default export.
Now if we head back over here, I can still use my default pi,
right?
And as I mentioned, we could call it capital PI or lowercase pi,
it does not matter. When I write importPI from this file
it's going to look for that default export, and it's going to set whatever this value is, this const
pi to a new variable essentially that we can now access inside our index.js file.
Now if I wanted to get hold of the other things that are being exported from this file, I can add a comma,
add a set of curly braces, and specify the names of the other things that are being exported inside here,
so in our case, it's doublePi and triplePi.
So let's go ahead and add those functions doublePi and triplePi.
Now in this case however, the names really do matter.
We can't just name doublePi
something else like double because it won't be able to recognize it from this list of exports. With the
default
there is only one and they can only be one default export per file,
but with these other ones, we differentiate them by their names.
So I have to make sure that I'm calling it the same as the export name. Once we've imported our doublePi
and triplePi,
I can now use it in my list item.
So for example maybe in this case, I want to use the value of doublePi,
but remembering that doublePi is a function,
so in order to get the value or the return out of it, I have to add the parentheses to activate it.
And now let's go ahead and do the same thing for triplePi as well.
And now you can see in our website we've got the value of PI which is exported as the default from math.js,
we've got the value of doublePi which is this function that's exported from math.js that
basically just returns the value PI multiplied by 2, and then triplePi multiplies it by 3.
And now we've got all 3 of these being rendered and all of these bits of functionality or const
values are coming from this single import statement from a completely different file. What import and
export and the concept of modules allows us to do is to really be able to start splitting up our large
JavaScript files into individual more manageable components.
And this is of course what the React components are leveraging from. And this capability is not new,
it's not unique to ES6 because even previously when we weren't using Babel, we weren't using ES6, when we
were just writing Node apps we were able to use the var react equals require react,
right?
So this code does pretty much the same thing,
but remember that this require function actually comes from Node itself, not JavaScript.
So if you're interested in, what exactly is the difference between the Node.js require, and the ES6
import/export, then a link to this Stack Overflow answer and question if you want to dive more into the
specifics. But just note that when we're working with Node, when we're not really sure that we can always
use ES6 because remember the browser penetration of ES6 is something like 80% at the moment,
so that means out of 100 users 20 of them might not actually be have to render this code that you're
using.
And so we're only able to very safely use ES6 everywhere in our app because we know that we're relying
on Babel to convert it into a format that can be rendered on any browser.
But I prefer the syntax of import and export because it's really clear what's happening. I'm importing
whatever is the default export from the react module and in this case I'm importing the default pi
which is being exported by math.js in addition to these two other functions which I'm going to use
inside my index.js file. Now if you don't want to actually separate out the difference between
the default and the exports, then in your import you can also just simply use the wildcard which is the
asterisks sign.
So this basically says, import everything but you have to give it a name so that you can use it in your
file, so you'll write import everything as we'll call it pi,
and then if we go ahead and console log what exactly is the value of PI anyways, then you'll see that
is actually an object and it has certain properties. It has something called doublePi() which is a
function, has something called triplePi() which is also a function,
and it also has a default property which is set to the value of whatever is being exported as the default
over here.
That means that we can now adjust our code instead of using PI,
we can write pi.default and then we can instead of doublePi, we can write pi.doublePi and
pi.triplePi.
And now if we refresh you can see that we've basically got the same thing as before, but we're now saying
we want everything from this entire module.
Why? If you use a wild card then you'll lose the benefit of having a single default export. Using the
single default export and incorporating specific functions makes your code more clear and it means that
you're only importing the things that you need.
This is why you'll see the wild card import discouraged in many style guides.
So in this lesson we looked at the import and export keywords.
We saw that in a single file, we can only have a single default export, but that default export can be
imported under any name you give it inside another file.
But if you wanted to get a hold of the other things that are being exported then you can add a comma
and a set of curly braces and then specify the exact names of the functions or constants or whatever
it is that you want to export from the other file.
And then once you've done that, you can then freely use these things that you've imported, either the
constants or the functions, and treat them as if they existed in this current file.
But it does mean that your files are split up.
They're easier to understand and it's easier to spot problems if there are any.
This way we can start building up more complex and more interesting apps that uses this kind of modularity.
In the next lesson
we're going to get some more practice using import and export
and I've got a challenge for you to complete.
So if you're happy with all the concepts learned in this lesson, and you think you can apply it yourself,
then head over to the next lesson and complete the challenge.