Logo

dev-resources.site

for different kinds of informations.

Bootcamping 02: Named exports and default exports - does it really matter?

Published at
11/24/2024
Categories
redux
es6
import
reducer
Author
aleflewitt
Categories
4 categories in total
redux
open
es6
open
import
open
reducer
open
Author
10 person written this
aleflewitt
open
Bootcamping 02: Named exports and default exports - does it really matter?

INTRO
One of the cool parts of writing code files, is the abstraction of different components of logic, and ultimate cooporation of those components as one organic unit, one application.

One of the syntaxes characteristic of ES6 is the ability to export units of logic from one file, and import them in multiple other files, making functions, data - and in React, JSX components - reusable. Write them once, and use them in many instances.

NAMED DEFAULT
Now, sometimes it's typical to have a utilities.js file, or any file for that matter, where the developer stores a host of logic. A bunch of functions, or pieces of data. A classic example is an api.js file which exports the various CRUD actions.

export function getData() {
//fetch data by making a GET request
}

export function createData() {
//create data by making a POST request
}

export function updateData() {
//update data by making a PUT request
}

export function (deleteData) {
//delete data by making a DELETE request
}
Enter fullscreen mode Exit fullscreen mode

Then, in our React component for example, in order to use one of these functions, we import it using { }:

import {getData, createData} from "../../src/api.js"
Enter fullscreen mode Exit fullscreen mode

EXPORT DEFAULT
In other instances, such as when creating a separate file for each React component, it's common to export the component in a "default" manner. This means that the logic being exported is the only export from that file, period.

For example, in a React App:

const MyComponent = () => <div>Hello, World!</div>;
export default MyComponent;
Enter fullscreen mode Exit fullscreen mode

Here, when utilizing this component inside the parent component, there is no need for the { } in the import statement:

import MyComponent from "./MyComponent"
Enter fullscreen mode Exit fullscreen mode

Apparently, the lack or presence of { } around the import, let the application know if it can expect or allow additional imports from the file, or if this import will be the only one.

REDUX REDUCERS
Is this the only reason though, for including the { } when importing a named import? Thanks to one of my students' questions today, we discovered another reason, at least when it comes to Redux reducer functions. We discovered that neglecting to place { } around a named import of a reducer function, serves to effectively "trick" the code into expecting a regular function, instead of a special redux reducer function.

Let's take a step back and describe one unique ability of Redux reducer functions. Here's an example of a standard slice file in a redux store, where we've created a reducer function called updateItemQuantity.

export const CartSlice = createSlice({
  name: "cart",
  initialState,
  reducers: {
    updateItemQuantity: (
      state,
      action: PayloadAction<IAddItemToCartPayload>
    ) => {
      const item = state.items.find((item) => item.id === 
      action.payload.id);
      if (item) {
        item.quantity += action.payload.quantity;
      }

      state.total = state.items.reduce(
        (sum, item) => sum + item.price * item.quantity,
        0
      );
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Notice how in the reducer function declaration, we've entered 2 parameters - state and action.

However, when calling this function in a component, we only pass it ONE parameter, and surprisingly Redux knows what to do with it!

  const handleAddToCart = (itemToAdd: IAddItemToCartPayload) => {
    dispatch(updateItemQuantity(itemToAdd));
  };
Enter fullscreen mode Exit fullscreen mode

Why is this?

The answer lies in the behind-the-scenes work that Redux does when we call dispatch. It automatically handles passing parameter 1 as the current state, and parameter 2 as an action object, and then takes the SINGLE parameter passed and injects it into the action object as a payload.

We discovered, that this all is well and good, as long as the export and import methods are consistent, as follows:
The reducer function is a named export:

export const { updateItemQuantity } = CartSlice.actions;
Enter fullscreen mode Exit fullscreen mode

and is also imported accordingly, complete with { }:

import { updateItemQuantity } from "../store/features/cartSlice";
Enter fullscreen mode Exit fullscreen mode

However, if the curly parentheses are left out, like such:

import updateItemQuantity from "../store/features/cartSlice";
Enter fullscreen mode Exit fullscreen mode

then what happens is as follows. Although the code editor recognizes the import, it displays an error that it expects 2 arguments for the function:

Image description

The error recorded is: Expected 2 arguments, but got 1.

The reason goes back to what we explained earlier - Redux knows how to handle the single parameter and inject it into the reducer function's second parameter (the action object). However, Redux only knows to do this if the exact reducer function exported is the same reducer function imported! When we left out the { } from the import statement, the code editor treated the updateItemQuantity as a regular javascript function and hence expected 2 parameters, just as there were 2 parameters when this (javascript) function was defined. However, only when we accurately imported it as the actual REDUX REDUCER function which was in-fact exported (by being precise with the { }) did the code editor recognize that this in-fact is NOT a regular JS function, but is rather a Redux reducer function, and hence is allowed to recieve only one parameter and leave the formulation of that parmater into the action object up to Redux to handle behind-the-scenes.

CONCLUSION

When you are learing how to code, you may find it tedious to stick to the details, like including curly parentheses versus leaving them out, but here's just another example of how a deeper understanding of what is going on behind the code, serves to help us appreciate the need for such attention to detail.

Happy learning!

es6 Article's
30 articles in total
Favicon
Next-Generation Buttons: Implementing the Command Pattern through Web Components
Favicon
Hoisting: facing Temporal dead zone
Favicon
Learn javascript promises. Part 1 β€” What is a promise?
Favicon
Bootcamping 02: Named exports and default exports - does it really matter?
Favicon
Mastering Modern JavaScript: A Deep Dive into ES6 Function Creation and Best Practices
Favicon
Promises: The Ability to Write Asynchronous Code Using Javascript
Favicon
Exploring JavaScript's Modern Primitives: BigInt and Symbol
Favicon
JavaScript ES6 Release Notes: Unleashing the Power of Modern JavaScript
Favicon
WHY YOU SHOULD LEARN ES6
Favicon
Understanding ES6 API's
Favicon
Transpiler vs Polyfills
Favicon
JavaScript Spread Syntax: Expanding Arrays and Objects
Favicon
API Design and Debugging:A Comprehensive Guide for BeginersπŸš€
Favicon
Understanding the JavaScript Spread Operator (With Examples)
Favicon
A Comprehensive Guide to ES6 and Arrow Functions
Favicon
Controla tus promesa con JavaScript
Favicon
Sets
Favicon
Enhanced Object Literals
Favicon
Iteration Stament i.e for-of loop
Favicon
1.1 Ins & outs of ES6(JavaScript) Import with Realworld Example and Demo Project.
Favicon
Math Namespace & BigInt
Favicon
JavaScript - Destructuring Arrays & Objects [Live Doc]
Favicon
ES2015 (ES6) Tips, Tricks, Best Practices, and Code Snippet Examples for Your Day-to-Day Workflow
Favicon
Objects in JavaScript
Favicon
Intro to DSA & Big O Notation
Favicon
Execution Context & Call Stack
Favicon
Asynchronous programming in Javascript - Callbacks, Promises & Async Await
Favicon
Loops in JavaScript !!πŸ“šπŸ”„
Favicon
Array
Favicon
Functions

Featured ones: