Should I avoid using "optional chaining" within the dependencies of a Hook?

Asked

Viewed 85 times

1

Today I noticed that I use the optional chaining (?.) within the dependencies of a hook:

useEffect(() => {
  // ...
}, [route.params?.addedProduct]);

It seems to work as expected, at least for now I have not observed unexpected behaviors. The point is that this operator ends up generating a code like:

(_a = route.params) === null || _a === void 0 ? void 0 : _a.addedProduct;

See an example on Playground

And if I try to make a comparison within Hook’s dependencies (route.params == null), I get the following Warning eslint:

React Hook useEffect has a Complex Expression in the dependency array. Extract it to a Separate variable so it can be statically checked. eslint(react-hooks/exhaustive-deps)

Just like the way it is now Warning, I don’t know if the Warning above is simply for validation of dependencies or if it really affects React, but Typescript ends up generating something different there. So I was left with the following doubt:

  • Use the optional chaining this way brings in some problem?
  • 1

    To those who have denied the question: please justify it. Where the question needs to improve?

1 answer

2


Like the optional chaining is a relatively recent addition to Javascript (standardized with Ecmascript 2020), Typescript (depending on the option target) can issue the code in order to function in old "environments".

That’s why this code:

const foo = {} as any;
console.log(foo?.bar?.baz);

Compile for this:

"use strict";
var _a;
const foo = {};
console.log((_a = foo === null || foo === void 0 ? void 0 : foo.bar) === null || _a === void 0 ? void 0 : _a.baz);

But note that the expression passed to the first argument of console.log will continue to evaluate for the same thing, agree?

Accordingly, in Runtime (apart from the additional code), there is no difference between using the optional string or that contraption there. The expression will always evaluate for the same result.

However, Eslint’s message is clear:

Extract it to a Separate variable so it can be statically checked.

When it comes to static environment, it can be said that it is the source code itself. In this case, it is quite different you use an expression little as foo?.bar?.baz than using the compiled result of Typescript (which, while also an expression, is much larger and therefore seems to require more of the static analysis done by eslint-plugin-react-hooks).

Note that although the expression always evaluates to the same thing, static analysis (which is under which Eslint and Typescript work) becomes more difficult in the second case. It’s more code to analyze.

The plugin eslint-plugin-react-hooks was created to "take care" of array of dependencies of useEffect (and similar). And probably, to "facilitate" the work, he asks to use expressions "less complex".

With this, I believe that it is okay to use optional chaining in the dependency array if the only concern is the difference between source code (Typescript) and "compiled" code. The expression will always evaluate for the same thing.

Even if you had used "compiled code" directly in your source code, Eslint would only ask you to extract the expression for a variable outside the array to be less "complex" - as the warning message itself says. I don’t know why, but he says that this would facilitate "static analysis". As it is static, it will probably have no influence on Runtime of your code, so you can use without fear.

  • 1

    Thank you very much for the answer. I distrusted That’s right, but I was a little put off by not finding the official documentation of this Eslint rule. The message actually hints that it is only for dependency analysis by the linter, and not a "programming problem". PS: Well-warned of the optional chaining having been included in Ecmascript, was not aware of this.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.