2

I came across this C# like code in a React project. I couldn't confirm if this syntax correct or not. I didn't find any recent ES version release to support this syntax. In current scenario I'm not authorized to execute and check this code.

I tried testing this syntax in browse console and encountered error:

{cart?.widgets?.items.map(widget => (
        <div className="billing-details__box" key={widget.id}>
          <p className="m-0">{widget.name}</p>
          <p className="my-0">{widget.value} $</p>
        </div>
 ))}

My concern with above code is whether cart?.widgets?.items will raise any error or not.

4

5 Answers 5

2

I couldn't confirm if this syntax correct or not.

It is correct TypeScript code, and is correct JavaScript depending on what engine you're running it in. Chrome (V8) supports this syntax already (see caniuse.com).

Here you can read more about the proposal to add this syntax to a future JS spec.

What is it?

This syntax is called the optional chaining operator, and it allows you to access properties that may or may not exist on an object without having to check for the properties existence no matter how deep the property access expression is.

For example, say we have some object like so:

const user = {
  details: {
    name: "SpongeBob SquarePants"
  },
  repo: null
};

And we want to get their name and, if it exists, some property user.repo.url. We can use the optional chaining operator to get both without having to worry whether repo is an object or not:

console.log(user.details.name) //=> "SpongeBob SquarePants"
console.log(user.repo.url) //=> undefined

It also works for function calls. For example, say when user.repo has a value we know it will be a function that returns a string. However, sometimes, as above, it may not be a function. We can do the following to call the function if it exists, but the code will not throw an error if the value at user.repo.url is not a function:

console.log(user.repo?.url()) //=> undefined

Without optional chaining operator?

You can achieve the similar behaviour to the optional chaining operator by explicitly checking the truthiness of each object property in the chain of properties that you are accessing.

This can be done either by taking advantage of JavaScript's short-circuit evaluation behaviour, or more obviously with the ternary operator.

It would look something like this:

function getItems_shortCircuit(obj) {
  return obj && obj.widgets && obj.widgets.items
}

function getItems_ternary(obj) {
  return obj 
    ? obj.widgets 
      ? obj.widgets.items 
        ? obj.widgets.items 
        : null 
      : null
    : null
}

let cart = {
  widgets: null
}

console.log(getItems_shortCircuit(cart)) //=> null

cart.widgets = {
  items: ["a", "b"]
}

console.log(getItems_ternary(cart)) //=> ["a", "b"]

My concern with above code is whether cart?.widgets?.items will raise any error or not.

It depends on whether the project is using TypeScript, which supports optional chaining (?.) out-of-the-box. You can read about it in the TypeScript documentation.

If you are not using TypeScript then you must compile your application using some ESNext compiler such as Babel, which has the @babel/plugin-proposal-optional-chaining plugin.

Sign up to request clarification or add additional context in comments.

5 Comments

You're a little wrong, optional chaining is actually correct JavaScript already and is live in Chrome 80+ (which is the default release currently) and Firefox 74+ (which is currently the dev release) right now. You will still need to transpile if you are targeting other browsers though. caniuse.com/#search=optional%20chaining
Yeah, I was really happy to see it go live in Chrome at the start of the month. Great answer!
I guess for other browsers, babel will transpile this code to supported javascript code
@VirajSingh That is correct - so long as you use the plugin linked in the answer, you can use this syntax everywhere once it has been compiled by Babel.
In case you didn't know, nullish coalescing operator ?? is live in Chome 80+ and regular Firefox (72+) now as well! Now we just need Safari and Edge to get with the program!
2

It is optional chaining which is JS new feature.

Basically it is the same as:

{cart && cart.widgets && cart.widgets.items.map(widget => (
        <div className="billing-details__box" key={widget.id}>
          <p className="m-0">{widget.name}</p>
          <p className="my-0">{widget.value} $</p>
        </div>
 ))}

For more details be sure to visit V8 guide.

Comments

1

It will be compiled by Babel and it will work. https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining

Comments

0

It's Optional Chaining and it should not cause any error if you use polyfills. "?." - is not supported by default yet

1 Comment

It is supported in Chrome (80+) and Firefox Developer Edition (74+) as of this month! caniuse.com/#search=optional%20chaining
0

That is probably the optional chaining from Typescript.

1 Comment

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.