Photo by Jay on Unsplash – Don’t get caught
Watch out when exposing a mutable data structure with React Hooks
When you spread an object instance of a class to expose methods, methods might not be copied over.
Suppose that you have a Trie
class,
which you want to make it immutable by returning a new object using syntax spread.
Not a good idea! Explained later.
Printing out trie
object instance returned from useTrie
won’t show has
and an empty method is printed.
Let’s see why and how to solve the issue.
🔬 Analysis
To understand the problem, let’s see how the class is transpiled using TypeScript compiler (the transpiled babel code does the same but verbose so using TypeScript compiler here).
has
method was added to the prototype, not to an instance of Trie
class.
So has
is still available when you do const t = new Trie(); t.has(); // true
.
Returning a new object using spread syntax didn’t copy has
because spread syntax only copies own & enumerable properties.
But prototype
is not enumerable so has
is not copied over.
🧙♂️ Resolving the Issue
You can resolve the issue in two ways.
-
Bindingthe method explicitly to
this
. - Using an arrow function expression.
1. Bind Explicitly
You can explicitly bind this
to the method in the constructor.
, which is TypeScript-transpiled as
And printing the trie
instance returned from useTrie
will now show .has
method.
has
is still added to the prototype
, which might not be what you want and it’s increasing the file size.
So this brings us to,
2. Using an arrow function expression
When you declare the has
method using an arrow syntax, it’s transpiled by Transcript as shown below.
You can see that it’s same without has
being assigned to the prototype
.
And the console log will still show has
as part of the trie
instance returned from useTrieUsingArrow
.
🤦♂️ Why? Why? Why?
I recently released a new package @cshooks/usetrie and Nick Taylor
generously provided an educational & thorough PR on how the code-base can be improved.
But not having a deep knowledge of TypeScript & Javascript, the following change caused an issue.
FYI – useTrie
is implemented as shown below.
I was retro-fitting a mutable data structure and exposing it as a hook.
But it’s not a good way as you can see between Paul Gray & Dan Abramov‘s tweets.
So be aware of the issue discussed above when you are extracting an imperative logic out of React.
🎉 Parting Words
I’ve paid handsomely for not following React way of doing things.
I hope you the gotcha & the workaround helped you understand what’s going on behind the scenes.
You can play around with the TypeScript transpiler on the Playground page
& the console log results in the Sandbox.
The post Spread syntax gotcha in JavaScript class methods appeared first on Sung's Technical Blog.
Top comments (2)
Thanks for the shoutout @dance2die . Happy I could help.
You're welcome & I could not have learned about this without your help 🙂