facebook / jsx

The JSX specification is a XML-like syntax extension to ECMAScript.
http://facebook.github.io/jsx/
1.96k stars 133 forks source link

Binding Syntax #27

Closed jacobp100 closed 2 years ago

jacobp100 commented 9 years ago

Report duplicated at https://github.com/facebook/react/issues/3090

I noticed that the new version of react will require manual binding. This problem will be lessened with ES7, but will still be there. I want to recommend an extension to the JSX language to bind functions to the scope: => over = (akin to arrow functions).

<button onClick=>{ this.onClick }>Submit</button>
sebmarkbage commented 9 years ago

It is not unreasonable.

I wonder, though, if the problem should be addressed on the method declaration side. Since it is useful to be able to bind these once and for all for an instance.

I like that in CoffeeScript the difference between a method and an auto-bound method is simply the single vs. double arrow.

  onClick: ->
  onClick: =>

The ES7 property initializer version isn't as elegant:

  onClick() {
  onClick = () => {

Perhaps it could be shortened to something like this?

  onClick() => {
jacobp100 commented 9 years ago

The issue is that React is starting to use ES6 classes, which we can't change the syntax for. But yes, your onClick = () => { ... } suggestion does work.

sebmck commented 9 years ago

@jacobp100 Not really an issue, transpilers can add whatever syntax they want.

jacobp100 commented 9 years ago

@sebmck This is for writing native ES6 with JSX. In current syntax, it follows this transformation.

<button onClick=>{ this.onClick }>Submit</button>
// becomes
<button onClick={ this.onClick.bind(click) }>Submit</button>
RReverser commented 9 years ago

Why not just check attribute's value and, when it's function, bind it to component automatically? Are there any cases where this will break things?

sebmck commented 9 years ago

@jacobp100 My response was in reply to:

The issue is that React is starting to use ES6 classes, which we can't change the syntax for.

Which isn't really true since transpilers can change and extend the syntax.

jacobp100 commented 9 years ago

@rreverser Since it's currently the default, I would presume nothing could break, so that would be an option. Not sure how easy it would be to implement that though (static analysis?).

@sebmck Wouldn't morphing ES6 classes to bund functions fall out of the scope of JSX?

syranide commented 9 years ago

I see three issues with this syntax:

  1. Double-binding <foo onBar=>{this.handleDelete.bind(null, id)} /> (because; bad habits)
  2. It should be a performance win to bind once at instancing than for every use at every render
  3. It seems weird to introduce a JSX syntax for something that seems best solved at the class-level

Or?

sebmck commented 9 years ago

@jacobp100 It would be which is why I didn't suggest that it to be added to the spec.

jacobp100 commented 9 years ago

For perf, maybe do this as part of the transform.

var onClick = this.hasOwnProperty('onClick') ? this.onClick : (this.onClick = this.onClick.bind(this));

(There will be one bound onClick on the object, and one unbound in the prototype)

I suppose this could also be a method provided by React to be called on construct().

RReverser commented 9 years ago

Not sure how easy it would be to implement that though (static analysis?).

Either static analysis where possible (in Flow for example) or just wrapAttributes(...) which iterates and binds functions before creating component.

sebmarkbage commented 9 years ago

@RReverser that is an interesting idea. However, it is a bit unclear what context it binds to, e.g. when used in a helper.

Another concern I have is that it might actually be best-practice to group related event handlers in nested objects to avoid giant single level property bags:

<Foo myHandlers={{ onClick: this.onClick.bind(this) }} />

instead of

<Foo myHandlers={this.onClick} />

Now that would mean that there are two subtly different ways of doing things.

In general, I think that it is a bad idea to add unrelated syntax sugar to JSX because the whole point of not using a template language is so that we can seamlessly go in and out of regular JS language.

I'd rather add syntax sugar to JS in general if it is needed. Like I we did with the spread attributes.

As @sebmck said, once there is a proposal for standardization it is trivial to start using such features with a transpiler.

jacobp100 commented 9 years ago

@RReverser Posted example code for that example in https://github.com/facebook/react/issues/3040 .

ghost commented 9 years ago

Thank you for reporting this issue and appreciate your patience. We've notified the core team for an update on this issue. We're looking for a response within the next 30 days or the issue may be closed.

dantman commented 8 years ago

I don't really like this idea. The => syntax isn't really even equivalent to arrow functions. Arrow functions allow {() => this.foo()} they simply have no this themselves, they aren't an auto-bind for a function passed to them.

In fact if => were to be used I think a much better use of the => syntax would be as syntax sugar that works like this:

// source
<Foo onClick=>{this.onClick()} />
// transpiled
<Foo onClick={() => this.onClick()} />

ie: The => would not bind but would be a JSX shortcut that makes the {} an arrow function.


Meanwhile I think that one of the stage-0 proposals may make this binding issue go away.

Specifically – as much as I kind of like the idea of something closer auto-binding more or some other syntax where this/*some special character here*/onClick (this could be any token, .., :, ->, or anything else) means this.onClick where the function is bound to the object it belongs to (the left hand side of the .) – I think we may instead end up inevitably moving towards es-function-bind.

<Foo onClick={::this.onClick} />
Huxpro commented 2 years ago

As React moving (primarily) to functional component, I think this proposals make less sense if it's particular considered for React.