1

I have trouble to mix autowire calls with scalajs-react components. Here is a simple example using scalajs-react v0.10.0 + autowire v0.2.5

case class User(name: String)

class Backend($: BackendScope[Unit, User]) {
  def mounted: Callback = {
    val future: Future[User] = AjaxClient[Api].getUser(123).call()
    //FIXME: how to get deal with it?
    CallbackTo { future.foreach(user => $.modState(_ => user)) }
  }
}

val Main = ReactComponentB[Unit]("Main")
  .initialState(User("N/A"))
  .backend(new Backend(_))
  .render { $ =>
    val name = $.state.name
    <.p(s"User name is $name")
  }
  .componentDidMount(_.backend.mounted)
  .buildU

State modification doesn't work here. How can I combine Future and Callback?

Update (27/10/15)

My autowire client

package example

import scalajs.concurrent.JSExecutionContext.Implicits.runNow
import org.scalajs.dom

import upickle._
import default._

import scala.concurrent.Future

object AjaxClient extends autowire.Client[Js.Value, Reader, Writer] {
  def write[Result: Writer](r: Result) = default.writeJs(r)
  def read[Result: Reader](p: Js.Value) = default.readJs[Result](p)

  override def doCall(req: Request): Future[Js.Value] = {
    println(req)
    dom.ext.Ajax.post(
      url = "/api/autowire/" + req.path.mkString("/"),
      headers = Map("Content-Type" -> "application/json"),
      data = json.write(Js.Obj(req.args.toSeq :_*))
    ).map(_.responseText)
     .map{t => println(t); t}
     .map(json.read)
  }
}
falcon
  • 372
  • 3
  • 19

1 Answers1

3

Adding some methods to make the combination of Callback+Future easier might be very helpful. Feel free to submit a PR, or even to raise an issue showing examples where additional support could be useful.

Until such helpers exist, you can just call .runNow() inside the future like this: Callback(future.foreach($.setState(_).runNow()))

Golly
  • 1,319
  • 8
  • 18
  • Thanks! Your advice was helpful. I've replace `AjaxClient[Api].getUser(123).call()` by `Furure(User("Mad Max"))`, added `runNow()` and realised that I have some truble with `autowire + upickle`. In my case even if replace `foreach` by `onComplite` them never called. – falcon Oct 23 '15 at 14:34
  • It could help your debugging if you add `.logAround`. Try this: `Callback(future.foreach($.setState(_).logAround("inside").runNow())).logAround("outside")` and then look in the JS console for messages telling you when inner & outer callback begin & end. – Golly Oct 24 '15 at 03:06
  • I added autowire client snippet. And there `.map{t => println(t); t}` is calling and printing response json to browser console. But `.map(json.read)` is not returning result. Maybe you can give me some advice about using autowite and upickle. – falcon Oct 27 '15 at 11:35