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

Implement valueLink and checkedLink #131

Closed
slorber opened this issue May 30, 2015 · 10 comments
Closed

Implement valueLink and checkedLink #131

slorber opened this issue May 30, 2015 · 10 comments
Labels

Comments

@slorber
Copy link

slorber commented May 30, 2015

I did not found valueLink and checkedLink in the list of available Html attributes.

https://facebook.github.io/react/docs/two-way-binding-helpers.html

Note that you can easily do 2-way data binding on a lens with valueLink.
I've done it here: https://github.com/stample/atom-react/blob/master/src/atomReact.js
Usage here: https://github.com/stample/atom-react/blob/master/examples/todomvc/js/components/TodoTextInput.react.js#L30

I think your ExternalVar example could be rewritten with a syntax like:

val NameChanger = ReactComponentB[ExternalVar[String]]("Name changer")
  .render { evar =>
    <.input(
      ^.`type`    := "text",
      ^.valueLink     := evar,
  }
  .build
@japgolly
Copy link
Owner

Hey @slorber, thanks for the time writing up with detail the issues you've submitted. (However I may go through them a little slowly - other OSS projects need some love and so does my main-work project :S)

My initial reaction to something like this is concern for type-safety, or rather, correctness provable by the compiler. If we were to implement something like this we'd want to ensure that the A in ExternalVar[A] matches what we can get/set in the underlying tag. For example, if one were to attempt to bind a String to a checkbox input we'd want that to be a compile-time error.

...which is think is doable, but I foresee it being a potentially significant amount of work. Maybe I'll give it a try on a branch sometime and see how it goes. Lens & prisms to tags could be a very good thing but tags' attributes determine the content type as much as tags themselves (eg. <input type="text"> vs <input type="checkbox">) which complicates things.

@slorber
Copy link
Author

slorber commented Jun 1, 2015

I understand your point.

Actually I think it could be simpler: valueLink takes an ExternalVar[String] and checkedLink takes an ExternalVar[Boolean]. I don't think this requires extra logic according to the input type unless you want to forbid using checkedLink for an input of type text for example which makes no sense

@japgolly
Copy link
Owner

Yeah that was what I was originally thinking (avoiding checkedLink on input(type=text) but I thought about it more, I think it falls into the category of acceptable dev mistake. We already have plenty of places where html & attributes can be used incorrectly anyway.

I was also thinking what specifically does this buy us? I guess it gives us 2 two things:

  1. One attribute valueLink instead of two (value & onChange).
  2. Extracts the event.target.value automatically.

Do you think it's worth it? I'm on the fence. Push me over it!

Also note to future self: add contramap to {External,Reusable}Var so that dev can use them with this and be able to modify incoming values on change.

@slorber
Copy link
Author

slorber commented Jun 15, 2015

I think this is exactly what you think it is: a syntactic sugar :)

Check the documentation: https://facebook.github.io/react/docs/two-way-binding-helpers.html

var WithLink = React.createClass({
  mixins: [React.addons.LinkedStateMixin],
  getInitialState: function() {
    return {message: 'Hello!'};
  },
  render: function() {
    return <input type="text" valueLink={this.linkState('message')} />;
  }
});
var WithoutMixin = React.createClass({
  getInitialState: function() {
    return {message: 'Hello!'};
  },
  handleChange: function(newValue) {
    this.setState({message: newValue});
  },
  render: function() {
    var valueLink = {
      value: this.state.message,
      requestChange: this.handleChange
    };
    return <input type="text" valueLink={valueLink} />;
  }
});

Both are equivalent.

As you can see the behavior is very simple
https://github.com/facebook/react/blob/ba81b60ad8e93b747be42a03b797065932c49c96/src/addons/link/LinkedStateMixin.js
https://github.com/facebook/react/blob/ba81b60ad8e93b747be42a03b797065932c49c96/src/addons/link/ReactLink.js

The React.addons.LinkedStateMixin and ReactLink are addons, but actually valueLink and checkedLink are parts of public React API so it would be nice to support these React attibutes too, and an appropriate integration of these API into your lib seems to be to link directly to ExternalVar

@japgolly
Copy link
Owner

Thanks @slorber. I am convinced :) I'll get this done.

@jimmydivvy
Copy link

As an additional note - if not already considered, it would be awesome if this could be written to an interface and not hardcoded to ExternalVar directly.

trait ValueLink[T] {
    value: => T
    requestChange: T => IO ()
}

I have a custom Cursor implementation that basically does the same thing as ExternalVar in a slightly different way. Would be nice to be able to bind directly to that instead of needing an implicit conversion.

@japgolly
Copy link
Owner

Aye, rest assured, I was thinking the same. There will be an open interface
without lock-in to ExternalVal or anything else internal. :)

On 29 June 2015 at 12:55, James notifications@github.com wrote:

As an additional note - if not already considered, it would be awesome if
this could be written to an interface and not hardcoded to ExternalVar
directly.

trait ValueLink[T] {
value: => T
requestChange: T => IO ()
}

I have a custom Cursor implementation that basically does the same thing
as ExternalVar in a slightly different way. Would be nice to be able to
bind directly to that instead of needing an implicit conversion.


Reply to this email directly or view it on GitHub
#131 (comment)
.

@japgolly japgolly added the could label Sep 13, 2015
@japgolly
Copy link
Owner

japgolly commented Oct 4, 2015

valueLink and checkedLink are being deprecated in React:
https://github.com/facebook/react/pull/5032/files

Note: This doesn't mean we have to care but I'd be interested in knowing why.

@slorber
Copy link
Author

slorber commented Oct 7, 2015

@japgolly the issue seems to be facebook/react#2302
Don't know but for a functional language I think using a "link" make sense as we are used to deal with lenses

@japgolly japgolly modified the milestone: neo Feb 22, 2017
@japgolly
Copy link
Owner

This feature still holds some appeal but when one thinks about it logically, we're talking about adding an abstracting so allow you to specify one vdom attribute instead of two. Given some of the major themes of the 1.0 rewrite were simplicity, transparency and readability, it's clear that it's not worth it. Let's just continue specifying two attributes every now and then and have it be clear how it all works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants