All Projects → aappddeevv → Scalajs Reaction

aappddeevv / Scalajs Reaction

Licence: mit
scala.js react bindings in the spirit of ReasonReact

Programming Languages

scala
5932 projects

Projects that are alternatives of or similar to Scalajs Reaction

Azure Core Concepts Book
A curated guide to get going fast on the Azure platform. Links, best-practices, explanations and comments, I wish I had known before I started using Azure.
Stars: ✭ 17 (-51.43%)
Mutual labels:  microsoft
Directxmath
DirectXMath is an all inline SIMD C++ linear algebra library for use in games and graphics apps
Stars: ✭ 859 (+2354.29%)
Mutual labels:  microsoft
Windows Theme
Repository for Windows 10 community subreddit stylesheet and its assets.
Stars: ✭ 29 (-17.14%)
Mutual labels:  microsoft
Teams For Linux
Unofficial Microsoft Teams for Linux client
Stars: ✭ 905 (+2485.71%)
Mutual labels:  microsoft
Node Vhd
Microsoft's Virtual Hard Disk (VHD) Format
Stars: ✭ 7 (-80%)
Mutual labels:  microsoft
Xlnt
📊 Cross-platform user-friendly xlsx library for C++11+
Stars: ✭ 876 (+2402.86%)
Mutual labels:  microsoft
Blogifier
Blogifier is an open-source publishing platform built with .NET Core 5.0 and the latest technologies.
Stars: ✭ 794 (+2168.57%)
Mutual labels:  microsoft
Microsoft Github Acquisition
Information & debate about the acquisition
Stars: ✭ 33 (-5.71%)
Mutual labels:  microsoft
Solrnet
Solr client for .Net
Stars: ✭ 853 (+2337.14%)
Mutual labels:  microsoft
Cloud Integration Beta
Docker CLI with ACI integration (beta)
Stars: ✭ 29 (-17.14%)
Mutual labels:  microsoft
70 483
compartilhamos conhecimento
Stars: ✭ 24 (-31.43%)
Mutual labels:  microsoft
Linux Microsoft Ie Virtual Machines
Run Internet Explorer 8/9/10/11/MS-Edge Virtual machines from Microsoft under Linux via VirtualBox.
Stars: ✭ 934 (+2568.57%)
Mutual labels:  microsoft
Awesome Windows Terminal
A collection of awesome things regarding the upcoming Windows Terminal
Stars: ✭ 20 (-42.86%)
Mutual labels:  microsoft
Azure Openshift
RedHat Openshift Origin cluster on Azure
Stars: ✭ 17 (-51.43%)
Mutual labels:  microsoft
Vscode Apimanagement
VS Code extension for Azure API Management.
Stars: ✭ 32 (-8.57%)
Mutual labels:  microsoft
Flaui
UI automation library for .Net
Stars: ✭ 892 (+2448.57%)
Mutual labels:  microsoft
Woa Installer Rpi
This repository was deprecated, use:
Stars: ✭ 865 (+2371.43%)
Mutual labels:  microsoft
Cn Vscode Docs
VScode说明文档翻译
Stars: ✭ 970 (+2671.43%)
Mutual labels:  microsoft
Botframework Solutions
Welcome to the Bot Framework Solutions repository which is the home for a set of templates and solutions to help build advanced conversational experiences using Azure Bot Service and Bot Framework. Microsoft Bot Framework is a comprehensive framework for building enterprise-grade conversational AI experiences.
Stars: ✭ 965 (+2657.14%)
Mutual labels:  microsoft
Magazine Website Akka
The experiment on the akkadotnet
Stars: ✭ 21 (-40%)
Mutual labels:  microsoft

Use react hooks and scala.js to catch the best user experience.

Bintray Maven Central with version prefix filter

You need to use a react version 16.8+ to make sure that hooks are included. Use the latest react-native.

Get started with the docs

What is scalajs-reaction?

A react library for scala written in the spirit of ReasonReact, a react library for an OCaml dialect known as reason sponsored by facebook. ReasonReact documentation provides a good description of how this library works since this facade was designed to mimic that facade. While more advanced scala functionality could have been used, the scala.js implementation is kept intentionally similar to ReasonReact so that its documentation applies to this project. However, you skip the ReasonReact documentation because this library uses simple scala/scala.js friendly constructs to create your user interface. Read on...

This library is small and focuses on simple js function components and hooks. Hooks are described on the react page.

scalajs-reaction emphasizes:

  • Easy to learn/use. Your component is just a standard scala.js js function.

  • Integration into an existing project by making it easy to import/export components. You just export the function.

  • Easy to fit into existing application including those using global state-managed solutions such as redux.

At the same time, it allows you to build your entire interface in scalajs-reaction. As long as your front-end solution can manage the model of scala.js's output (one large module for all scala.js code, not file-by-file/module-by-module), you should consider scalajs-reaction for your solution. By providing a thin veneer over standard scala functions and hooks, it eschews abstractions and avoids getting in your way.

The library supports fragments, the new context provider and hooks. The facade's API roughly mimics ReasonReact's approach based on hooks. This facade also supports react-native. The react-native use-case for scala.js is actually more compelling than for web applications due to scala.js bundling issues. There is also API support for experimental APIs.

A g8 template is available. Use sbt new aappddeevv/scalajs-reaction-app.g8 to create a new project.

Creating Components

It's easy to create a component and render it:

val HelloWorld: ReactFC0 = () => div("hello world")
// ...
react_dom.createAndRenderWithId(HelloWorld, "container")

ReactFC0 does not do much other than ensure that the scala function on the right becomes a js function--which is all that is needed to use react. You could have just declared it directly:

val HelloWorld: js.Function0[ReactNode] = props => div("hello world")

If you need to pass in an argument, remember that react function components requires only a single js object parameter, so do the following:

object MyComponent {
    trait Props extends js.Object {
        val name: String
    }
    // I use this declaration style alot.
    val render: ReactFC[Props] = props =>
      div("hello " + props.name)
    }
    render.displayName = "MyComponent"
    def apply(props: Props) = createElement(render, props)
}

ReactFC says that the function component HelloWorld takes a single parameter, of type Props. You do not need to use ReactFC, you could just use standard scala and standard react:

object MyComponent { 
    trait Props ...

    val render: js.Function1[Props, ReactNode] = props => div(s"hello ${props.name}")

    def apply(props: Props) = createElement(render, props)
}

or with types and extension methods:

object MyComponent {
  trait Props ...

  // A standard scala function is a val, but its better to type it as ReactFC[Props]
  val render: Props => ReactNode = props => div(s"hello ${props.name}")

  // A standard def scala function, it's better to use a val
  //def render(props: Props): ReactNode = div(s"hello ${props.name}")

  // ReactElementTuple causes scala=>js function conversion using standard scala methods
  def apply(props: Props): ReactElementTuple = (render, props)

  // r convert using the `.elementWith` extension method which reads nicely
  // This is what I usually use.
  def apply(props: Props) = render.elementWith(props)
}

That's how simple this facade is. You use the easy parts of scala.

To create a higher-order component or a "container/pure renderer" design, use function composition:

def withPageLogging[P <: js.Object](component: ReactFC[P]): ReactFC[P] = props => {
  useEffectMounting(() => println("LOG PAGE!"))
  createElement(component, props) // or component.elementWith(props)
}

A few, very limited macros provide additional support creating and using Props more like case classes if that's important to you. Once scala3 is out, the macros will become industrial strength.

React needs to control when the props are applied to the rendering function, not you. A react "element" is really just a data structure that is a description of the element's rendering logic and props. The actual rendered element is created under react's control, not yours. There are other component specification patterns you can use as well or you can easily create your own like the above. See the docs.

If you want to ensure your component only renders when the props change, use memo(). memo uses shallow compare checking to see if the props have changed. An extension method is available for memo to apply it as syntax. You need to take into account js's notion of equality when using function components and hooks or provider your comparator, something useful when you have scala objects in your props.

Add state and other effects to your component using react hooks just like you normally would.

The facade implementation in scala.js is only about 50 lines of code and is easily maintained. Various conversion and extension methods are provided to make it easier to use.

You have choices on how to create your components and they are all straightforward. Depending on the component library you use, having choices helps you find the easiest way to access the components in your application. This library does not force many conventions on your code.

This facade uses standard scala.js concepts. Higher level components, e.g. composition of smaller components, can use more idiomatic scala constructs. This library does not fight scala or scala.js to make it more like js. It uses the tools provided by scala and scala.js to make it easier to write react applications and control react rendering optimizations.

Usage

Include the library in your build:

resolvers += Resolver.bintrayRepo("aappddeevv", "maven")
val scalaJsReactVersion = "latest.version" // see the badge above 

// grab the the latest version or use a specific version
libraryDependencies ++= Seq(
    "ttg" %%% "react" % scalaJsReactVersion,
    "ttg" %%% "vdom" % scalaJsReactVersion,

    // optionals
    // if you need react-dom
    "ttg" %%% "react-dom" % scalaJsReactVersion

    // Microsoft fabric UI components, "MS office", css-in-"scala"
    // css-in-scala can be used independently of fabric
    "ttg" %%% "fabric" % scalaJsReactVersion,

    // Material UI components (bootstrap is also available but limited)
    "ttg" %%% "mui" % scalaJsReactVersion,

    // if you integrate with redux
    "ttg" %%% "redux" % scalaJsReactVersion,
    
    // if you need prop-types--you only need these for interop scenarios
    "ttg" %%% "prop-types" % scalaJsReactVersion,
 
    // if you need react-native
    "ttg" %%% "native" % scalaJsReactversion)
//
// Add import scala.language.implicitConversions to each file or
// add scalacOptions += Seq("-language:_") to your settings 
// to enable implicit conversions and all other language features
//

Do not forget to include the react libraries in your execution environment. For react 16+, the libraries have been split out into multiple libraries. For the reactjs based modules, the javascript dependencies are:

  • core: react
  • react-dom: react-dom
npm i --save react
npm i --save react-dom

React 16.8+, the one with hooks, is required. Some experimental APIs are supported so you may want to use the latest experimental release.

There are many modules available as most of the focus has been on hand-crafted bindings in order to improve ergonomics. We'll work with ScalablyType to improve the availability of bindings, however, they are quite simple to write using scalajs-reaction. All of these libraries use the group name ttg:

  • apollo
  • bootstrap
  • dataloader
  • data-validation (applicative data validation)
  • express
  • fabric (office-ui-fabric-react): Custom and ergonomic facade.
  • fabric-experiments
  • forms: Advanced, all-scala.js forms package.
    • In transition so its not currently available.
  • formik
  • handlebars
  • helmet
  • jshelpers: Helpers for working with js data. Includes full js.Promise extension methods to avoid Future.
  • jss
  • lodash
  • loglevel
  • luxon (datetime library, evolved from moment)
  • msal
  • mssql
  • mui
  • native
  • pathtoregexp
  • plotlyjs
  • prop-types
  • react
  • react-content-loader
  • react-device-detect
  • react-dom
  • react-big-calendar
  • react-fast-compare
  • react-native-nativebase
  • react-native-elements
  • react-navigation
  • react-native-sideswipe
  • react-plotlyjs
  • react-redux
  • react-responsive
  • react-helmet
  • react-flexbox-grid
  • react-router-dom (5 and 6)
  • recoil (facebook state management)
  • use-query-params
  • use-deep-compare-effect
  • vdom
  • whydidyourender (use include/exclude regexs, see the readme in that directory)

Some of the external libs have just enough scala.js to write an app with but they are not fully fleshed out. In most cases, there are enhancements to make using the library easier, however, scala3 will introduce some refinements to the scala language that will make many things easier and I have chose not to try and be too clever until scala3 arrives. Most of the packages use a simple namespace hierarchy starting with the package name versus "ttg" or "scalajs-reaction" or anything complicated. You are likely only to use one set of react libraries per application so you should not encounter any package namespace collisions.

In many cases, the full package label has been dramatically shortened to make it easier to import the content you need. The package names closely mirror the javascript libraries themselves.

You will most likely also need DOM bindings. Here's a link to the api for org.scala-js scalajs-dom bindings: javadoc.

Documentation

Client:

Integrated API documentation:

Sometimes the documentation generation process does not work so if you need docs it is probably best to generate them locally.

Generate integrated documents using unidoc then open the toplevel page:

get clone https://github.com/aappdddeevv/scalajs-reaction
sbt "docs/unidoc"
# linux has xdg-open to open a file from the command line
xdg-open website/scalajs-reaction/static/api/index.html

Demo

You can start the demo locally if you run sbt npmRunDemo. A browser page should open automatically. If not, point your browser to https://localhost:8080. You can also just load the demo files (after its built) into your browser but note that the icons will not render correctly since they require a fetch.

Argh!!! I'm having trouble with gh-pages so the demo probably does not work at htis time. Run it locally after you clone the repo.

Motivation

I was looking for a react facade that rethought reactive interactions. Many of the existing facades are straight adaptions of the standard react library and make it quite easy to program react in a scala environment.

The ReasonReact facade, using a modified OCaml syntax, keeps it quite simple. This library is actually quite small and simple and relies on functions. Scala.js easily supports creating classes that map into javascript classes and hence into react component classes. However, with parallel fiber coming to react and other enhancements that are planned, a more functional library should withstand the change in the core react infrastructure to something that is more sustainable in the long run.

Suitability

Scala.js requires a bundling model that does not allow it to be broken apart and deployed on a pure "file/module" basis. Because of this, scalajs-react is best suited for UIs where it is not required to code split the scala portion of the library unless some type of fancy splitter can split apart optimized scala.js emitted code. Scala.js makes use of optimizations, such as inlining, and integrated type infrastructure that makes it difficult to split.

The core scala.js infrastructure costs you about 2.5k and increases as you use features such as immutability, the collections library or, of course, add data structures to your code.

Related

There are a few scala.js react facades/implementations available:

The facades differ in their facade approach but many recreate all of the API parts found in reactjs. japgolly works hard to put a more safe, functional API in place from the outset. Some of these facades have alot of complex facade components to help deal with the type and side-effects flexibility found in react.

In theory, all of these can "export" a scala.js component to be used in javascript environments. However, various libraries that go deep into scala-land means that they are harder to use from javascript land often because they wrap the javascript props and state objects in a way that makes them less usable from the javascript world. Most, if not all, libraries allow you to use javascript defined components fairly directly via some type of adoption or import process.

Libraries you may be interested in:

  • binding.scala: reactive UI framework. It uses a new binding framework for scala. Works on jvm and js. The binding framework is at a individual element level like mobx. You can use xml syntax as well. The binding approach is called "precise" binding.
  • diode: redux replacement.
  • laminar: a reactive web framework.
  • levsha: Fast pure scala.js virtual dom.
  • pine: XML/HTML builder.
  • scalacss: A solid css-in-scala solution.
  • scala-dom-types: for dom attributes.
  • scala-tags: XML/HTML builder.
  • outwatch: reactive UI framework.
  • udash is another reactive framework that is not react based, but reactive.
  • udash-css: A css-in-scala framework.

License

MIT license. GitHub license

Copyright 2018 The Trapelo Group LLC.

The logo was created partially from content provided by Scott De Jonge under CC3.0.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].