This repository includes adapters for React / Binding.scala / html.scala interoperability.
The rendering process in React components is unpredictable, resulting in unnecessary reevaluation and, even worse, unexpected reevaluation of side effects, if any. Precise data-binding in Binding.scala is a fast and predictable alternative to React's repeatedly re-rendering approach.
However, currently there are more third-party components in the React ecosystem than Binding.scala. It would be nice if a web developer could reuse React components while taking advantage of Binding.scala's precise data-binding. This repository includes the following adapters for reusing React components in Binding.scala + html.scala web apps:
@html
literal or an html"..."
interpolation.@html
literal or an html"..."
interpolation into React virtual DOM..bind
data-binding in React virtual DOM.With the help of the adapters, you will be able to reuse existing React components while getting rid of React hooks or setState
by managing your app's states in Binding.scala.
// build.sbt libraryDependencies ++= Seq( "com.yang-bo" %%% "html" % (if (scalaBinaryVersion.value == "3") "3+" else "2+"), "com.yang-bo" %%% "bindingreacttoreact" % "1+", "com.yang-bo" %%% "reacttobindinghtml" % "1+", "com.yang-bo" %%% "bindinghtmltoreact" % "1+", )
The following example demonstrates how to use React components with html.scala's @html
literal in Scala 2
import com.thoughtworks.binding.Binding import com.thoughtworks.binding.Binding._ import com.yang_bo.ReactToBindingHtml.Implicits._ import com.yang_bo.BindingHtmlToReact.Implicits._ import com.yang_bo.BindingReactToReact.Implicits._ import org.scalajs.dom._ import org.lrng.binding.html import slinky.web._ import slinky.web.html._ import slinky.core.facade._ @html def spinner(currentNumber: Var[Int]): ReactElement = { // virtual DOM span element span( // real DOM button element <button id="minus" onclick={ (event: MouseEvent) => currentNumber.value -= 1 } >-</button>, // virtual DOM label element with Binding.scala's `.bind` magic Binding { label(currentNumber.bind.toString) }, // virtual DOM button element button( id := "plus", onClick := { (event: Any) => currentNumber.value += 1 } )( "+" ) ) } val currentNumber = Var(50) @html val rootView = { // real DOM fieldset element <fieldset> <legend> I am an `@html` literal that contains a React component </legend> { spinner(currentNumber) } </fieldset> } html.render(documet.body, rootView)
For Scala 3 users, use html.scala's html"..."
interpolation instead, as shown below:
import com.thoughtworks.binding.Binding import com.thoughtworks.binding.Binding._ import com.yang_bo.ReactToBindingHtml.Implicits._ import com.yang_bo.BindingHtmlToReact.Implicits._ import com.yang_bo.BindingReactToReact.Implicits._ import com.yang_bo.html._ import org.scalajs.dom._ import slinky.web._ import slinky.web.html._ import slinky.core.facade._ def spinner(currentNumber: Var[Int]): ReactElement = { // virtual DOM span element span( // real DOM button element html"""<button id="minus" onclick=${ (event: MouseEvent) => currentNumber.value -= 1 } >-</button>""", // virtual DOM label element with Binding.scala's `.bind` magic Binding { label(currentNumber.bind.toString) }, // virtual DOM button element button( id := "plus", onClick := { (event: Any) => currentNumber.value += 1 } )( "+" ) ) } val currentNumber = Var(50) val rootView = { // real DOM fieldset element html"""<fieldset> <legend> I am an html interpolation that contains a React component </legend> ${ spinner(currentNumber) } </fieldset>""" } render(documet.body, rootView)
Even though adapters from this repository provide the flexibility to choose to create UI in either React or real DOM, to minimize the cost due to React rerendering, BindingReactToReact
users are recommended to neither define any React components nor use any React hooks. Instead, to take the advantage of Binding.scala's precise data-binding, manage the application states in Binding.scala, and let the BindingReactToReact
React components be instantiated implicitly, when using existing React components.
Because React virtual DOM does not support partial update provided by Binding.scala's BindingSeq
, create your own HTML UI as @html
literals or html"..."
interpolations, if the overhead due to React's virtual DOM differentiation matters.
Adapters from this repository work with React types defined in Slinky by default. Other sources of React components need to be converted to Slinky types first.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4