DEV Community

Aki Rautio
Aki Rautio

Posted on • Edited on • Originally published at akirautio.com

Optional chaining with React

13.1.2020 UPDATE: Babel 7.8.0 supports optional chaining out of the box

Optional Chaining is one of the most requested features in Javascript (and Typescript) which is no wonder since it solves a very fundamental problem; accessing the property from a dynamic deep object safely.


// A deep structure example 
const deepObject = { 
  firstLevel: { 
    secondLevel: { 
      thirdLevel: 'value' 
    }
  }
}

// Accessing thirdLevel safely without optional chaining
const thirdLevelValue = (((deepObject || {}).firstLevel || {}).secondLevel || {}).thirdLevel

// Accessing thirdLevel safely with optional chaining
const thirdLevelValue = deepObject?.firstLevel?.secondLevel?.thirdLevel

Enter fullscreen mode Exit fullscreen mode

The main advantage of using optional chaining is a smaller and cleaner code which makes it easier to comprehend once people get used to the syntax.

How to use optional chaining

Last autumn Optional Chaining proposal got to the Candidate stage (stage 3) which means that the specification is very close to the final version. This change resulted it to be part of Typescript 3.7 in late October 2019 and Create React App 3.3.0 at the beginning of December 2019. Also supporting tools like Prettier have already added the support.

If you are using one of these, then optional chaining should work out of the box. At the current state (December 2019) the major editors like VSCode may need a bit of configuration to handle the new syntax but I would expect this to be changed very soon. If you have some trouble, check Configuring VSCode to handle optional chaining-topic from below.

Using Optional chaining with Babel

Typescript or CRA is luckily not the requirement to use optional chaining when developing with React. You can do the same with Babel 7.8.0 and greater or with optional chaining plugin (@babel/plugin-proposal-optional-chaining)

Since babel usually isn't used alone but as part of the toolchain, the required packages may differ from setup to setup. If you are starting to use babel, I would suggest to first follow one of these tutorials / repos:

  1. Babel setup
  2. Babel with Webpack
  3. Babel with ParcelJS

If you have older than 7.8.0, you need to install optional chaining plugin with following command:

npm install --save-dev @babel/plugin-proposal-optional-chaining

and adding it to .babelrc

{
  ...,
  "plugins": ["@babel/plugin-proposal-optional-chaining"]
}

Enter fullscreen mode Exit fullscreen mode

After this you should have a working setup.

Configuring VSCode to handle optional chaining

As a default, VSCode uses typescript checking for Javascript React code and currently this isn't supporting optional chaining. There are ways to fix this:

  1. Install ms-vscode.vscode-typescript-next extension which adds support for new typescript features including optional chaining to

  2. Disabling typescript and javascript checking and installing and setting Eslint extention to VSCode and configuring eslint to handle optional chaining.

Configuring Eslint to handle new syntax

Eslint needs a babel-eslint package to understand the new syntax.

npm install --save-dev babel-eslint

It also needs addtional configuration to .eslintrc

{
  "parser": "babel-eslint",
  ...
}


Enter fullscreen mode Exit fullscreen mode

Advantages to use optional chaining compared to other options

If you have been developing with Javascript (and especially with React) for some time, you may have used some functions to handle dynamic longer paths that shouldn't fail. It may have been either internally develop a solution or a function from the external package like Get from Lodash or Path from Ramda.

All these functions are still as usable as they used to be but using a future native way in code makes it more future proof and reduces the amount of external code needed. Right now the optional chaining needs to be always transpiled but that won't be the case in the future. Once browsers and NodeJS start supporting it, the transpiling can be dropped without the need to change the code.

Top comments (4)

Collapse
 
slashgear_ profile image
Antoine Caron

Hey !

I don't really agree with the conclusion of your article.
Using this feature now is quite dangerous for you web performances. The way babel is transpiling the optional chaining is quite disgusting (ok, like every polyfill), but this one is not really necessary.

If you try to use it everywhere is your apps, you should notice that your bundle will swell quickly.

I wrote an article explaining why we should avoid this feature for now.

Collapse
 
akirautio profile image
Aki Rautio

I would agree that performance wise it's not the best and the transpiled code looks ugly. But if this starts to cause performance issues, I would rather optimize the Babel transpiling than trying to fix it inside the application. Transpiling won't be eventually needed for most of browsers so this is a "temporary" issue.

Collapse
 
p4lm profile image
Henrik Sommerfeld

I really like this. For my Gatsby project with VS Code, all I had to do was to click the TypeScript version number (which was 3.6.3) in the Status bar and choose Use Workspace Version 3.7.3. Done!

Collapse
 
akirautio profile image
Aki Rautio

Oh so cool :) That's even easier way to get VSCode to work with this!