Webpack allows us to organize the code into modules. Every variable or function is private in a module and has to be explicitly exported to become public. Public content is visible and can be imported by the other modules. That said, popular strategies like IIFE (Immediately Invoked Function Expression) are no longer necessary to avoid polluting the global scope with undesired variables or functions.
On the Webpack configuration file, we set a module as an entry-point. Then Webpack will resolve the modules imported by the entry-point, as well as all the other modules imported by subsequent modules. Through a long module-by-module scan, Webpack creates a dependency tree and connects them into a single file called bundle.
As we can see in the image, all the necessary modules to resolve the entry-point were included in the bundle. The bundle contains index.js (entry-point), a.js, b.js e c.js. Since no module imported d.js during the entry-point resolution, it was left out. This is nice because it means that modules that are not effectively used by the application are not bundled, avoiding unnecessary weight.
In this repository, you can check the .babelrc and webpack.config.js configuration files containing only what is minimally required to bundle and run a React application.
The way to handle HTML is where you will see most of the differences between AngularJS and React. Bindings, Loops and Conditional Rendering work radically different in React.
AngularJS has a philosophy called Two-Way Data Binding. Through the ng-model directive, AngularJS binds the controller variable to the template and vice versa. When the variable changes on the controller, the template is automatically updated. And when the user changes the variable on the template, the controller gets updated as well. Also, a child component can change the value of a property passed by its parent. That is, not only parents change a property value given to its children, but also children change the property values received by their parents.
React treats binding differently. It is One-Way Data Binding. The value of a variable present on the controller reflects automatically on the template, but when the variable changes on the template, its value is not automatically updated on the controller. You need to handle this change manually. Component property values can only be updated upside down too. That is, from the parent to the child, not otherwise.
Playground: Two-Way Data Binding, One-Way Data Binding.
It was also using another directive that parts of a template could be conditionally rendered in AngularJS. All you needed to do was passing a Boolean variable to the ng-if directive to decide if the element and its children would be shown or not.
Playground: Ng-if, If Statement, Operador &&, Operador Ternário.
Playground: Ng-repeat, Map.
But the main differences between AngularJS and React are not limited to the template engine. The Component Lifecycle API changes a lot as well.
Lifecycle hooks give us the necessary conditions to perform specific tasks. When some tasks only can be done after the component template has already been rendered, we can use the component initialization hook, for example. On the other hand, if we need to perform a task at the moment in which a component is removed from the DOM, we can use the component termination hook.
The hook that represents the component initialization in AngularJS is $onInit. This is the function AngularJS runs at the moment in which component is fully ready for use. That is, the template is rendered, and all the variables present on the controller are bound to it.
Tasks that need to be performed in specific moments of the React component lifecycle are passed to a function called useEffect. Not so intuitive, the name of this function relates to the term side effect. Within useEffect we can be sure that the task will run only after the component is mounted.
Playground: $onInit, useEffect.
Like the tasks that should be run when the component is already mounted, some other tasks need to run right before component unmounts. Consider some task adding an event listener to the document at the moment the component initializes. That listener must be removed from the document when the component is removed from the DOM. Otherwise, every initialization of that component will add one more listener causing unexpected behavior.
The AngularJS hook that allows us to run a task right before a component is removed from the DOM is called $onDestroy.
The hook used in React to do this keeps the same, useEffect. In the previous case, initialization, we just passed a function to the hook that will be run at the moment in which the component is fully mounted. When you need to run a task right before the component is unmounted, the function passed to useEffect must return another one. That other one should contain the tasks that will run right before the end of the component life.
Playground: $onDestroy, useEffect.
As we noticed, the underlying logic on how to handle a component does not change too much from AngularJS to React as the code appearance may suggest. Once you understand the differences regarding the form, any developer familiar with AngularJS will have no trouble developing React components.