2017-04-22 65 views
1

我正在使用scalajs 0.6.15與scalajs-react 0.11.3和reactjs 15.4.2。如何使用類型參數化組件與scalajs-react

考慮組件SomeComp,其中需要參數化Props的值的類型。

由於在使用組件構建器時需要知道類型,因此我將該組件包裝在類中。

class SomeComp[T]() { 
    case class Props(t: T, onChange: T => Callback) 

    val component = ReactComponentB[Props]("SomeComp")... 

    def apply(t: T, onChange:T => Callback) = component(Props(t, onChange)) 
} 

這有效。問題在於,組件每次重新裝載父組件時都會重新裝入組件,除非SomeComp的用戶首先創建SomeComp的實例並在父組件的render方法中使用此實例。

我砍的解決方案,以避免這就是:

object SomeComp { 
    val genericComp = SomeComp[Any]() 

    def apply[T](t: T, onChange: T => Callback) = genericComp(
    t = t, 
    onChange = (a: Any) => onChange(a.asInstanceOf[T]) 
) 
} 

有沒有更好的,boilercode,少可怕的呢?有什麼建議麼?


更新 後@天哪的(!THX爲您精心製作的答案)建議我找到第二個解決方案最優雅,並希望它張貼在這裏的完整性:

object SomeComp { 
    trait Props{ 
    type T 
    val t: T 
    val onChange: T => Callback 
    } 

    // use Props#T if you need to reference T 
    val component = ReactComponentB[Props]("SomeComp")... 

    def apply[_T](_t: _T, _onChange: _T => Callback) = { 
    val props = new Props { 
     type T = _T 
     val t = _t 
     val onChange = _onChange 
    } 
    component(props) 
    } 
} 

回答

1

我做了幾多年來嘗試多態組件並放棄完美。如果我們接受較小的缺陷,那麼有足夠的,甚至是很好的解決方案:

1a)圍繞建造者的類。你的第一個例子除了之外有一個重要的區別:只爲每個類型創建一個類。在未安裝創建同一類型結果一類新/重新安裝,你看到(因爲陣營認爲成分是不同的),在那裏,如果你做這樣的事情:

final class SomeComp[A] private[SomeComp]() { 
    val component = ReactComponentB[Props]("SomeComp")... 
} 
object SomeComp { 
    val Int = new SomeComp[Int] 
    val String = new SomeComp[String] 
} 

如果你不不知道類型是否提前,也沒關係,只需創建類型一次,並將其放入調用對象的伴隨對象中。這是一個小缺陷,你需要創建一個單一的類型,但一切其他仍然很簡單。

1b)與上面類似,除了使用函數而不是類。每個類型創建一次(每個被調用者可選)並重用。

2)我不會推薦這個,但你可以使用存在類型而不是通用類型,特別是使類型參數成爲類型成員。

class Props { 
    type T 
    val value: T 
    val onChange: T => Callback 
} 

現在該組件是單形的,但您需要一些樣板來創建和使用Props類。

順便說一句,如果你自己創建(T×T→回調),可以使用內置的代碼:https://github.com/japgolly/scalajs-react/blob/master/doc/EXTRA.md#statesnapshot(doc是1.0.0-RC1 +,以前是兩類: {可重複使用,Exeternal} Var在1.0天前)

+0

thx爲'StateSnapshot'提示! – trudolf