Optional Chaining: The Nullish Nuisance You Didn’t Know You Needed

Darshit AnjariaDarshit Anjaria
4 min read

Unlocking the Power of Optional Chaining in JavaScript

Have you ever felt the frustration of trying to access a deeply nested property in an object, only to hit a wall of undefined?

Let me share a little story about how I navigated this common challenge in JavaScript and how I discovered a feature that changed my coding game: optional chaining.

Scene 1: The Nesting Nightmare

It all started when I was tasked with developing a feature for a web application that displayed user profiles. Each profile had nested data structures that contained information like user details, preferences, and even social media links. Here’s a simplified version of the object I was dealing with:

const userProfile = {
  name: "Alice",
  address: {
    city: "Wonderland",
    postalCode: "12345",
  },
  socialMedia: {
    twitter: {
      handle: "@alice",
      followers: 1000,
    },
  },
};

I needed to access the user's Twitter handle, but I wasn't sure if the socialMedia object would always exist. What if the user had not linked their Twitter account?

The Traditional Approach: A Risky Business

Before I discovered optional chaining, I would write code like this:

const twitterHandle = userProfile.socialMedia && userProfile.socialMedia.twitter && userProfile.socialMedia.twitter.handle;
console.log(twitterHandle); // If socialMedia or twitter is undefined, this returns undefined.

This approach worked but was clunky and hard to read. Not to mention, if any part of the chain was undefined, I would end up with an error or an unexpected undefined result.

Scene 2: The Discovery of Optional Chaining

One day, while browsing through the latest JavaScript updates, I stumbled upon a magical feature: optional chaining (the ?. operator). This nifty syntax allows you to safely access deeply nested properties without having to check each level of the object.

Here’s how I rewrote the previous example using optional chaining:

const twitterHandle = userProfile.socialMedia?.twitter?.handle;
console.log(twitterHandle); // Returns undefined if socialMedia or twitter doesn't exist

Just like that, I could access the Twitter handle without worrying about undefined errors!

How Does It Work?

Optional chaining is like a safety net. Here’s a breakdown of how it operates:

  • Syntax: The ?. operator allows you to access the next level of an object only if the previous level exists.

  • Return Value: If any part of the chain is undefined or null, the expression short-circuits and returns undefined instead of throwing an error.

Scene 3: Common Use Cases

Q: Where can I use optional chaining in my code?

  1. Accessing Nested Properties: As shown in the user profile example.

  2. Calling Functions: If a function may not exist on an object:

     const result = userProfile.getProfile?.(); // Safely calls getProfile if it exists
    
  3. Accessing Array Elements: In arrays, optional chaining can be handy for checking if an item exists:

     const firstFollower = userProfile.socialMedia?.twitter?.followers[0]; // Returns undefined if followers is not an array
    

Scene 4: Potential Drawbacks

Q: Are there any downsides to using optional chaining?

While optional chaining is incredibly useful, there are a few things to keep in mind:

  • Readability: Overusing optional chaining can make code harder to read, especially if there are many nested properties. Use it wisely!

  • Performance: Although the performance impact is generally negligible, unnecessary use in performance-critical code could be a consideration.

Scene 5: Real-Life Scenario

Recently, I worked on a project that required fetching data from a REST API. The API responses were inconsistent, with some fields missing entirely. Instead of adding multiple checks for every nested field, I utilized optional chaining throughout my code. This not only simplified my code but also made it far more resilient against errors due to missing data.

Here’s a quick example from that project:

fetch('/api/user/123')
  .then(response => response.json())
  .then(data => {
    const profilePicture = data.user?.profile?.picture;
    const bio = data.user?.bio ?? "Bio not available"; // Use nullish coalescing for default value
    console.log(profilePicture, bio);
  });

Final Thoughts: Embrace the Change

Incorporating optional chaining into my coding practices has made a noticeable difference. It allows for cleaner, more maintainable code while reducing the risk of runtime errors. If you haven’t tried it yet, I highly recommend giving it a shot!

So the next time you’re faced with deeply nested properties, remember: optional chaining can save you from the headaches of undefined errors and help you write more elegant JavaScript.


Thank You!

Thank you for reading!
I hope you enjoyed this post. If you did, please share it with your network and stay tuned for more insights on software development. I'd love to connect with you on LinkedIn or have you follow my journey on HashNode for regular updates.

Happy Coding!
Darshit Anjaria

0
Subscribe to my newsletter

Read articles from Darshit Anjaria directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Darshit Anjaria
Darshit Anjaria

Experienced professional with 4.5+ years in the industry, collaborating effectively with developers across domains to ensure timely project delivery. Proficient in Android/Flutter and currently excelling as a backend developer in Node.js. Demonstrated enthusiasm for learning new frameworks, with a quick-learning mindset and a commitment to writing bug-free, optimized code. Ready to learn and adopt to cloud technologies.