Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Component setState doesn't allow Symbol keys #6372

Closed
gingur opened this issue Mar 29, 2016 · 13 comments
Closed

Component setState doesn't allow Symbol keys #6372

gingur opened this issue Mar 29, 2016 · 13 comments

Comments

@gingur
Copy link

gingur commented Mar 29, 2016

https://jsfiddle.net/gingur/eqprn74c/

When trying to do something like this.setState({ [someSymbol]: 'someValue' }); the render is being invoked properly but the this.state[someSymbol] is undefined. Running Object.getOwnPropertySymbols on this.state I have confirmed that this.setState does not define Symbol properties.

@gaearon
Copy link
Collaborator

gaearon commented Mar 29, 2016

What is the use case for using Symbols as state keys? State is already private and is never shared so it’s not clear what the benefit of supporting Symbols as keys is. Would you mind sharing your thoughts on this?

@gingur
Copy link
Author

gingur commented Mar 29, 2016

Sure, check out https://jsfiddle.net/gingur/4ury0beq/2/. The idea is a Symbol can be provided as a prop to map a "dynamic" state property. Now given, this could also be accomplished with unique strings but the use case at least is demonstrated.

@zpao
Copy link
Member

zpao commented Mar 29, 2016

cc @sebmarkbage

Basically this boils down to the fact that the Object.assign "polyfill" we have inside React doesn't handle symbols. We just use that to assign the pending updates into the current state -

var nextState = assign({}, replace ? queue[0] : inst.state);
for (var i = replace ? 1 : 0; i < queue.length; i++) {
var partial = queue[i];
assign(
nextState,
typeof partial === 'function' ?
partial.call(inst, nextState, props, context) :
partial
);
}
. We knew that going in when we first added it but that was a long time ago and symbols are a real thing that browser support now so maybe we should too.

@aweary
Copy link
Contributor

aweary commented Mar 29, 2016

@zpao if it was just the Object.assign() pollyfill then wouldn't this already work with browsers that have a native Object.assign() implementation that supports Symbols? Just curious.

edit: Oh I see, it doesn't actually use the native Object.assign() ever. Would making this module return the native Object.assign() when it's supported resolve this? Or is there a behavior this implements that the native Object.assign() method doesn't?

@zpao
Copy link
Member

zpao commented Mar 29, 2016

No, it's a "polyfill" which we always use and never fall back to native implementation. This was because at the time of adding this, the Object.assign spec had just changed (around handling null/undefined I think) so we decided to always use our own code for consistency. Here's the code: https://github.com/facebook/react/blob/22a3d0387b190eed4689937a375ce22b1338803b/src/shared/stubs/Object.assign.js

@aweary
Copy link
Contributor

aweary commented Mar 29, 2016

So would you be open to a PR that checks for symbols as well in assign? I'd be happy to work on it if this is something you guys would like to see.

@zpao
Copy link
Member

zpao commented Mar 29, 2016

I don't know yet, would like to get input from @sebmarkbage about intent before deciding how to fix it (personally, I think if yes we would likely just get rid of our polyfill and use babel-polyfill/runtime for it or even just say that you must include a polyfill of your own like we have for ES5 code)

@sebmarkbage
Copy link
Collaborator

Yea, we should use native if available. Either using our own module or a mandatory external polyfill. Probably best to keep our own if a native is not available. Easy to miss the polyfill warning if you're only testing in modern browsers.

@aweary
Copy link
Contributor

aweary commented Mar 29, 2016

The Object.assign module could just be updated to return the native Object.assign function if it exists and Symbol support could be added when it doesn't using something similar to what the object-assign pollyfill does

@gingur
Copy link
Author

gingur commented Mar 30, 2016

So to be clear, is the purposed solution to eventually rely on the consumer to implement appropriate polyfill (ie https://github.com/zloirock/core-js/blob/v2.2.1/modules/_object-assign.js via babel-polyfill) or for the https://github.com/facebook/react/blob/master/src/shared/stubs/Object.assign.js to be replaced by something like https://github.com/ljharb/object.assign?

@aweary
Copy link
Contributor

aweary commented Mar 30, 2016

@gingur #6376 discusses that, with the later option (using object-assign) being the preferred solution so far.

@gingur
Copy link
Author

gingur commented Mar 31, 2016

Would be nice if there was a react-polyfill repo, allowing the consumer to choose to either supply their own pollyfills (ie babel-polyfill) or to use the ones needed for react to run itself. Would also allow node to run react without the need of the polyfills.

@zpao
Copy link
Member

zpao commented Apr 1, 2016

Worth noting that there are very few cases of these. We've long used ES5 but ES6 is mostly compiled out or we provide our own polyfills (Object.assign as a module, Object.is inlined are the only 2 I know of). The idea of a react-polyfill repo is interesting though and definitely something we'll keep in mind moving forward.

@zpao zpao closed this as completed in #6376 Apr 4, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants
@zpao @sebmarkbage @gaearon @gingur @aweary and others