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

Shorter prop usage syntax #20

Open
labe-me opened this issue Feb 25, 2015 · 3 comments
Open

Shorter prop usage syntax #20

labe-me opened this issue Feb 25, 2015 · 3 comments

Comments

@labe-me
Copy link

labe-me commented Feb 25, 2015

Hello,

I've been using the project for some days and was really pleased by the lib except for the syntax part which suffer from react/js legacy.

The problem with Props() is that it forces you to type a lot of things and when you start to use apply(...) = apply(Props(...)) you have to type three times your parameters to keep things in sync which is a pain.

I just found a method to shorten the syntax but I haven't tested it a lot so your comments are welcome :

// This is our Props()
case class UserRankingLine(pos:Int, name:String, image:String, score:String)

// A component to display a Ranking
object UserRankingLine extends TypedReactSpec {
  // our Props is the case class
  type Props = UserRankingLine
  // this implicit will run the .apply(o:Props) whenever a Props() needs to be converted into a ReactDOM
  implicit def toReactDOM(o:Props) : ReactDOM = apply(o)

  // our state as usual
  case class State()
  def getInitialState(self:This) = State()

  // render the component
  @scalax def render(self:This) = {
    <div className="UserRankingLine">
      <div className="rank">{ self.props.pos }</div>
      <img src="{self.props.image}" alt="" width="50" height="50" />
      <div className="name">{ self.props.name }</div>
      <div className="score">{ self.props.score }</div>
    </div>
  }
}

And then you can instantiate your component just like with the regular Component.apply(...) method :

@scalax def render(self:This) = {
  UserRankingLine(1, "User", "img/foo.png", "1000 pts")
}

Maybe the implicit can be pushed up into the hierarchy so users don't have to type it everytime or maybe the case class type could be given as a generic parameter so the implicit could be created inside the TypedReactSpec[T]. I am not sure what could work with the project.

There may be problems with Seq[Component], I am not sure implicits will be run correctly to get Seq[ReactDom], I haven't tested it yet and you may see problems coming :)

Anyway thank you for the awesome work and I hope this little trick will be of some help to simplify the API.

@labe-me
Copy link
Author

labe-me commented Feb 25, 2015

React.renderComponent() is not happy with the method, I have to cast the component to ReactDOM before invoking the renderComponent().

It's no big deal and it works but I am pretty sure it could be improved with a different signature, visible as ReactDOM (<%) instead of extending ReactDOM (<:) not sure about the side effects though.

inferred type arguments [react.PlaceCast] do not conform to method renderComponent's type parameter bounds [C <: com.xored.scalajs.react.ReactDOM]

@labe-me
Copy link
Author

labe-me commented Feb 26, 2015

I just extracted the type and the implicit into a trait and I am pretty happy with the syntax now :

import com.xored.scalajs.react._
import com.xored.scalajs.react.util._

trait Component[T] extends TypedReactSpec {
  type Props = T
  implicit def toReactDOM(o:Props) : ReactDOM = apply(o)
}

This little trait make this possible :

case class MyComponent(name:String, value:String)

object MyComponent extends Component[MyComponent] {
  case class State()
  def getInitialState(self:This) = State()

  @scalax def render(self:This) = {
    <div className="MyComponent">
      { self.props.name } = { self.props.value }
    </div>
  }
}

Best,
Laurent

@labe-me
Copy link
Author

labe-me commented Feb 26, 2015

Damned :)

This solution pose a problem with optional case class parameters, more work is needed.

in object Button, multiple overloaded alternatives of method apply define default arguments.
[error] The members with defaults are defined in object Button in package react and trait ReactSpec in package react.

Also in some cases the @scalax fail to cast the property class into a ReactDom which is cumbersome.

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

1 participant