0

Question on simple example:

Assume we have :

1) 3 functions: f(d:Dependency), g(d:Dependency), h(d:Dependency)

and

2) the following function call graph : f calls g, g calls h

QUESTION: In h I would like to use the d passed to f, is there a way to use the cake pattern to get access to d from h? If yes, how ?

Question on real-world example:

In the code below I manually need to thread the Handler parameter from

// TOP LEVEL , INJECTION POINT

to

//USAGE OF Handler

Is it possible to use the cake pattern instead of the manual threading? If yes, how ?

package Demo

import interop.wrappers.EditableText.EditableText
import interop.wrappers.react_sortable_hoc.SortableContainer.Props
import japgolly.scalajs.react.ReactComponentC.ReqProps
import japgolly.scalajs.react._
import japgolly.scalajs.react.vdom.prefix_<^._
import interop.wrappers.react_sortable_hoc.{SortableContainer, SortableElement}

object EditableSortableListDemo {

  trait Action
  type Handler=Action=>Unit

  object CompWithState {

    case class UpdateElement(s:String) extends  Action

    class Backend($: BackendScope[Unit, String],r:Handler) {
      def handler(s: String): Unit  =
      {
        println("handler:"+s)
        $.setState(s) 
        //USAGE OF Handler <<<<<=======================================
      }

      def render(s:String) = {
        println("state:"+s)
        <.div(<.span(s),EditableText(s, handler _)())
      }
    }

    val Component = (f:Handler)=>(s:String)=>
      ReactComponentB[Unit]("EditableText with state").initialState(s).backend(new Backend(_,f))
      .renderBackend.build
  }

  // Equivalent of ({value}) => <li>{value}</li> in original demo
  val itemView: Handler=>ReqProps[String, Unit, Unit, TopNode] = (f:Handler)=> ReactComponentB[String]("liView")
    .render(d => {
      <.div(
        <.span(s"uhh ${d.props}"),
        CompWithState.Component(f)("vazzeg:"+d.props)()
      )
    })
    .build

  // As in original demo
  val sortableItem = (f:Handler)=>SortableElement.wrap(itemView(f))

  val listView = (f:Handler)=>ReactComponentB[List[String]]("listView")
    .render(d => {
      <.div(
        d.props.zipWithIndex.map {
          case (value, index) =>
            sortableItem(f)(SortableElement.Props(index = index))(value)
        }
      )
    })
    .build

  // As in original demo
  val sortableList: (Handler) => (Props) => (List[String]) => ReactComponentU_ =
      (f:Handler)=>SortableContainer.wrap(listView(f))

  // As in original SortableComponent
  class Backend(scope: BackendScope[Unit, List[String]]) {
    def render(props: Unit, items: List[String]) = {
      def handler = ??? 

     // TOP LEVEL , INJECTION POINT<<<<<<========================================

      sortableList(handler)(
        SortableContainer.Props(
          onSortEnd = p => scope.modState( l => p.updatedList(l) ),
          useDragHandle = false,
          helperClass = "react-sortable-handler"
        )
      )(items)
    }
  }

  val defaultItems = Range(0, 10).map("Item " + _).toList

  val c = ReactComponentB[Unit]("SortableContainerDemo")
    .initialState(defaultItems)
    .backend(new Backend(_))
    .render(s => s.backend.render(s.props, s.state))
    .build
}
jhegedus
  • 20,244
  • 16
  • 99
  • 167
  • In your simple example, you can just pass `d` to `g` in `f` and to `h` in `g`. No cake needed. – Jasper-M Dec 08 '16 at 09:58
  • 1
    An alternative would be to use implicit parameter instead of cake pattern. You still have to define that on every function, but at least you don't have to explicitly pass it along the call chain. – Haspemulator Dec 08 '16 at 10:50

0 Answers0