I am new to React and I've come across two bits of code that I think do the same thing, but I am not entirely sure.
import React from 'react'
export default function TestComponent() {
return (
<div>
</div>
)
}
as well as
import React from 'react'
function TestComponent() {
return (
<div>
</div>
)
}
export default TestComponent
The only difference that I can see between the two is that the export is just put at the end in one of them but they should both behave the same if my understanding is correct. Does this have any real effect on the behaviour of the code?
As several in the comments have already said, those two code blocks are practically equivalent (ie. they are the same). In theory you could add code to make them different (eg. you could re-assign the function before exporting it in the second example) ... but it would be pretty contrived.
Does this have any real effect on the behaviour of the code?
No. What matters is just that you name your exported functions at all (and in fact the Create React App rules will fail if you don't, because it could make your debugging harder).
It's the same thing in your case because you are creating your React component by using a 'classic' Javascript function.
I personnally use the first code to save a line but the second code is usefull when you have a React.js component written in arrow function like as is :
const yourComponent = () => {};
export default yourComponent;
In this case, you must use this line at the end of your file :)
Both code blocks are functionally the same but I personally favor the second.
Both use a function declaration but the second one permits you to swap the declaration out for a function expression or class declaration without modifying the export.
Also, in cases where you can have multiple exports from a single file, it's a useful convention to declare the default export at the bottom of the file.
All in all, that's not a matter for React or components, but for coding in general and JavaScript modules especially.
It might be matter of scalability on the dev side, i.e. how you yourself will be able to manage your code if it grows. If you have to add and maintain more functions / classes / variables, it's a benefit to separate the place in code where you define the functions / classes / variables from that where you define wich to export and from that where you define your default export because you can only have one default export, but many non-default exports - imagine you decided to re-declare which export is the default one, labeling the new one as "default" and forget to "de-label" the old one, then with defining "default" somewhere in your code the old default might outrule the new one because being later in the code. Declaring exports at the end of file will give you helpful overview.
As question of personal style might be if you want to use "export" directly where a function / class / variable is defined to see immediately what functions / classes / variables are "public" and which are "private" (i.e. not exported).
If your code grows into something requiring some kind of an API, you might use the option to export as, e.g. maintaining complicated "speaking" functions names inside of your code, but exposing the functionality by "simple" names to the component's consumers. This would be obviously easier if being separated from the definitions of the functions itself.
In general, for your own sake, be as explicit as possible, here: separate "export" instructions. Trying to have short and clever code leads to more complexity than myriads of "stupid simple" code. React and other soft- and hardware is not impressed how cleverly you may have code golfed, very rarely something would be faster or slower, since optimization should not be part of developing, and trying to generalize should be well dosed.
For JavaScript "ES6" modules used by React for components, the 2015 introduction https://hacks.mozilla.org/2015/08/es6-in-depth-modules/ is still the best reference and surely a must-read.
Both are technically same, the only difference is that you add an extra line to export your functional component in second code. I generally prefer second code because it keeps my code clean when compared to first code.
Related
I'm building a large React application that involves processing lots of data, formatting it and outputting to tables. Occasionally these functions are variables (e.g const x = () => etc.)
I'm storing the functions that do this formatting in Typescript files which I import into my React components.
To give an example, I might write a table formatting function like this:
export const buildMainData = (data: any) => {
do stuff
}
I'm placing it inside a file, called functions.ts (for example).
I then have a React component which makes use of the function.
My question is - is this a bad idea? Am I creating loads of functions that are polluting the memory heap? I'm using create-react-app so I'm not sure if Webpack is doing some magic behind the scenes to prevent global variables, or whether everything I write should be placed inside of React components.
It would be great if anyone with more experience / knowledge in this area could help out. If I'm also completely getting the wrong end of the stick that would also be helpful to know. Thanks.
The variables and functions you're exporting aren't globals, they're exports from the module in which you define them. They're used via import. If you have some that aren't used, modern bundlers like Webpack and Rollup can tree-shake the bundle they create, leaving unused functions out (if there are any). More about tree-shaking in Webpack and in Rollup.js.
It's true that top-level declarations in classic scripts are globals, but top-level declarations in modules are scoped to the module (kind of like the module were a function and you were declaring things inside it), and then possibly exported from it.
I've found at least two ways to import functions in from a module like Ramda for example. There are probably a few more ways to do something very similar like const R = require('ramda');
Option 1 is to import certain functions:
import { cond, T, always, curry, compose } from 'ramda';
Option 2 is to import the whole module like:
import * as R from "ramda";
I would prefer to reference the module from which the function is being called like so:
R.T();
But if the 2nd option is used, does it bring in every Ramda function not just the ones used in a module I'm working in? Are there any impacts on actual memory use, or bandwidth use as far as what gets sent to the browser if option 2 is used?
Is it possible to somehow do this:
// invalid syntax below:
import R { cond, T, always, curry, compose } from 'ramda';
R.T();
My question is kinda related to this one, but it's a bit different
import R (ramda) into typescript .ts file
TL;DR: It does not matter.
import * as … from 'ramda';
import { … } from 'ramda';
will both by default always bring in the complete Ramda module with all its dependencies. All code inside the module would be run, and which syntax was used to reference the exported bindings doesn't matter. Whether you use named or namespaced imports comes down to preference entirely.
What can reduce the file size to download and the used memory is static analysis. After having evaluated the module, the engine can garbage-collect those bindings that are referenced from nowhere. Module namespace objects might make this slightly harder, as anyone with access to the object can access all exports. But still those objects are specified in a way (as immutable) to allow static analysis on their usage and if the only thing you're doing with them is property access with constant names, engines are expected to utilise this fact.
Any size optimisation involves guessing which parts of the module need to be evaluated and which not, and happens in your module bundler (like Rollup or WebPack). This is known as Tree Shaking, dropping parts of the code and entire dependencies when not needed (used by anything that got imported). It should be able to detect which imports you are using regardless of the import style, although it might have to bail out when are doing unusual things with the namespace object (like looping it or using dynamic property access).
To learn about the exact guesses your bundler can make, contact its documentation.
#Bergi is right in his comment, which I think should be the answer. I would also like to point out you can always try things out in Babel to see what it compiles to: click here to see what an example destructuring actually does
So basically even if you destructure just one function from the module, the whole module will be required. In the Babel example I gave, I just extracted Component from the 'react' module, but the compiled code actually just required the whole thing. :)
Adding to #Bergi, Also just for future reference if you want to shed unused functions and import only the desired function, use selective import like below
import isEmpty from 'ramda/src/isEmpty';
This way you can complement it with Webpack and get a better tree shaking. Hope it helps
This question is about ES6 not about global variables.
When the new ES2015 export or export default were introduced. They were made so that you can import/get the same variables, values or items somewhere else using import. So I have a simple question. Why should we use export and import instead of just making a simple object of a class and getting items through it or just making static or global variables?
I know the fact that it can be used to make your code much cleaner and also to put the code easily into multiple files but let's just assume we have first.js and second.js and we have a variable called names in the first.js that we want to get in the second.js. Now you can either do that with import and export or by making an object in the second.js and accessing our variable by that object. So why is it better to use export and import?
export was introduced to be used alongside import (you need to explicitly declare what you need to later import), as part of the ES2015 module standard.
Before these standard modules were implemented, splitting up Javascript code into multiple files and not have all objects pollute the global object was only possible using sort short of non-standard module definition and/or module loaders like RequireJS. The simplest case was to wrap your code in Immediately Invoked Functions. ES6/2015 just standardize Javascipt modules.
Now you asked why not just have Javascript objects even in many files? The answer to that is namespacing
Actually - you make a good point.
namespace stuff is in C++. There are lots of people who think it is cool to have a namespace indicator in front of everything they use.
So, instead of saying { cout << my_string << endl; }, their whole program has { std::cout << my_string << std::endl; }.
Sometimes you see stuff like { disk::io::byte::bit::atom::neutron::quark::say_hi(2) }. And, the guy who wrote that thinks he's a super developer.
But, as they are purist, it more likely you will see { std::cout << myString << endl; } because camel case is so much more preferential than human readable strings.
Now, in node.js I am always doing something like const ClassFromMod = require('mod-with-class'). In the file, you have to say module.exports = ClassDeclaredInHere. I always do this, because really, is there any other way provided?
Or you can do this const {ClassFromMod} = require('mod-with-class').
Then you have to have, module.exports.ClassFromMod = ClassDeclaredInHere.
So, doing the same thing in the browser is sort of OK. But, now global contexts and local contexts are harder to work with - really. Just a little harder sharing things between modules when you have to. But, not to worry almost all of the time people partitions their modules just right. That's because they are people - in fact the sort of people who are more cautious than those in charge of nuclear reactors - because those people do some web programming. So, no Chernobyl when it comes to partitioning modules. Right?
Now, you can get your hands into a class def. And, the class is itself something of a namespace.
So, then why is there not a global registry of classes? Only that maybe different companies (individual developers) will use the same name for two remotely different classes. But, likely there would be some way around that.
One way might be to assign classes to uses (sort of name spacey). But, it might be more categorical. Like "engine" for something with a car feature, or "engine" for something that runs a script. Programming languages might have something like "talking about cars here". What would that be like?
start>> talking about cars <
let bval = engine.rev()
if ( bval ) {
<about scripts> engine.run("small program")
}
<<stop talking about car
That's an idea. Looking at it, I don' like it. It's sort of like "with" that lots of languages use.
So, with new strictures imposed on the programming environments, you get bugs and scope troubles that add to your long long long day. But, you should get that your question drawn from clear thinking is in some sense being steamrolled by a small group of people who can. And, you can take out the trash for them.
So, what about identifying objects by features and enabling sort of a flat namespace management? Could be driven by AI. Could have been done thirty years ago. But, now is now. But, the future exists for correcting the mistakes of the past.
Suppose I define a simple React functional component like this:
const Greeter1 = ({name}) => <h1>Hello {name}</h1>;
I can also define an equivalent plain-old JS function that returns a React element, like this:
const Greeter2 = name => <h1>Hello {name}</h1>;
The "React" version is of course also just a normal JS function, taking in a JS object instead of a string. We could use either of these functions within plain JS to get the greeter element for a given name, just with slightly different caller syntax:
const greeterElement1 = Greeter1({ name: "Bob" });
const greeterElement2 = Greeter2("Bob");
Within a React expression though, we can call these functions in a few different ways:
const someReact1 = <div>{ Greeter2("Bob") }</div>;
const someReact2 = <div>{ Greeter1({ name: "Bob" }) }</div>;
const someReact3 = <div><Greeter1 name="Bob" /></div>;
My question: Are there any effective differences between these calling styles other than syntax aesthetics? I assume someReact1 and someReact2 are virtually identical, but I'm not sure about someReact3. Does using the React component syntax change the way React treats things? Does it affect behavior or performance in any way? Or is it merely syntactic sugar?
When doing a diff on the virtual DOM tree, does React forgo comparing within a functional component if its attributes haven't changed between renderings? And if so, am I correct to assume that that optimization would be lost when calling functions directly as in someReact1?
I want to know b/c in some cases I actually prefer the style of someReact1 as it allows me to use functional programming techniques like currying more easily, plus sometimes it's nice to not have to specify parameter names when calling. But am I paying some kind of penalty by doing so? Am I better off sticking with the traditional syntax?
Component functions are (a bit?) faster than class components since React 16. Not sure if it's true for prior versions.
Calling component function as a function is much faster than calling it via JSX/React.createElement.
But, in most cases, this should not affect the way we write our code since JSX is pretty readable. To fill this gap we should use #babel/plugin-transform-react-inline-elements.
However, I understand your passion to call them as functions. For the sake of composition, I also find it quite useful. This is even more true for plain functions.
But, again, in the future, functional components are going to have a state. If it happens, we may regret our passion :)
Plain functions seem to be faster than component functions. However, I have not digged this topic yet. For example, I'm unsure if it works OK with react-hot-reload. Or, its pros/cons for performance and possible optimizations.
IMO, no matter the differences and in any case, optimizations are still on us - be it a shouldComponentUpdate, or memoization, or keys. Components which might not need any optimizations should be cheap to re-render, and vice versa (if it is a pure calculation, not DOM operation, obviously).
Feel free to comment or correct, I'll update my post.
I found an explanation, apparently someone asked a similar question in a Github issue on the official React repository. Here's a link to the issue https://github.com/facebook/react/issues/16796 and an excerpt from the thread, an answer provided by a contributor:
What I want to understand is this: Is it actually necessary to call
React.createElement again, since it is already in the return value of
the component? Is there any effective difference between that and
calling the function component directly, like this?
As #hamlim mentioned, the effective difference is that simply calling a component as a function wouldn't work if the component was more complex than a pure function that returned another React element. React needs the element returned from React.createElement to handle those features.
In the HelloMessage example you could technically just call it as a function, which would be equivalent to doing:
ReactDOM.render(
<div>Hello Taylor</div>,
document.getElementById("hello-example")
);
This just inlines the result of HelloMessage, which would render the same UI in the browser. Thats effectively what you're doing by calling HelloMessage as a function. Internally this would be different to React since there's no component mounted, but practically speaking the behavior is identical in this trivial example.
For the ParentComponent example, the same constraints apply. You could call the ChildComponent components as functions if they were just simple components without state or effects, and that would be the same result as just inlining their content into ParentComponent. In same cases this might be what you want, but typically not. If someone added state or effects to one of the ChildComponents, or wrapped it in React.memo or React.lazy, this would break. So use this pattern with caution.
I am learning design pattern in JavaScript, and I'm going to use the module pattern. I'm puzzled with two things.
1 - If I would create a plugin, then I can use the module pattern, and have private and public methods/variables. But if I have a full JavaScript file, I don't need private and public methods, since one part of the program has nothing to do with another part. So what's the point of private and public methods?
2 - Since the JavaScript file is really long, should I have nested module's? How should I go about a full file of JavaScript?
JavaScript has moved on. ES6--which there is no real reason not to move up to, if you haven't already--has its own modules. So there is no need to "simulate" modules with old patterns. Example:
// Old style.
var myModule = function() {
var privateVar;
function getPrivateVar() { return privateVar; }
return {getPrivateVar: getPrivateVar};
}();
console.log(myModule.getPrivateVar());
// New style.
let privateVar;
function getPrivateVar() { return privateVar; }
export {privateVar};
// Using it
import {getPrivateVar} from './myModule';
console.log(getPrivateVar());
In the above, privateVar is by definition private to the module (file). There's no need to keep it private by wrapping it in an IIFE. Instead of handling the exports ourselves as properties of a single returned object, we use the ES6 export mechanism to export it explicitly.
(1)
When all Javascript files are loaded, all the scripts in all files are just like they are in one file. Script in one file can access (read, update, delete) global variables in other files. There are a lot of questions on this, you can easily search for those.
Of course, "one part of the program has nothing to do with another part", but in case you are in team with many members, each works on a part of the system (or in some cases, a file). Then, there is a chance that one person accidentally changes variables created by another person. Those kinds of error are quite easy to detect. But if you can modularize you script, you can avoid those kinds of error altogether.
(2)
You can go slow. While writing code to complete requirements, try to recognize the parts of code that can be separated to a modules (or even nested modules). Them put them into other files.
You should be creative and careful while doing so. The code might grow very fast and things get out of control very quickly.