Skip to content

Latest commit

 

History

History
361 lines (291 loc) · 15.5 KB

2.0.0.md

File metadata and controls

361 lines (291 loc) · 15.5 KB

2.0.0

Lots of big, juicy, modernising changes here. Make sure you at least read the migration guide.

Contents:

Major New Features

  • Scala 3 support

  • React Hooks (doc)

  • React 17

    • Contexts now have optional displayNames. You can optionally specify it on creation via React.createContext(displayName, defaultValue). You can also read it via .displayName.
    • Add disableRemotePlayback HTML attribute
    • Add enterKeyHint HTML attribute
  • Effect generalisation:

    • You can now provide any kind of supported effect in place of just Callback(To) in many cases. Eg. you can now pass an AsyncCallback to an event handler without converting it to a Callback.
    • Additional effect types can be used by including the appropriate module; no imports required. Eg. if you include the Cats Effect extension module you can pass an IO directly to scalajs-react.
    • The default effect types are now configurable. Default effect types are used when scalajs-react provides you with effect values. Eg. calling .props from BackendScope used to be hardcoded to return a CallbackTo[Props] because CallbackTo used to be hardcoded as the default sync effect type.
      • If you use the core module then everything will be the same as it was with Callback(To) and AsyncCallback being the default sync and async effect types respectively.
      • If you use the new core-bundle-cats_effect module instead of core, then Cats Effects' SyncIO and IO types will be the default sync and async effect types respectively.
    • The Callback(To), AsyncCallback, CallbackOption classes are now optional. If you use a different core bundle (eg. core-bundle-cats_effect instead of core) then classes like CallbackTo wont even be on the classpath unless you explicitly add the callback module.
    • If you're a scalajs-react library author, there's a guide just for you: Creating an Effect-Agnostic Library.
  • Modularity. There are now many more modules (i.e. Maven artifacts) that are smaller and more pluggable, for increased flexibility. For example, the React Scala.JS facades now live in their own modules without any other scalajs-react specific functionality. (doc)

  • Global settings have been fixed and revamped. See the new guide here. This allows you to produce different dev and prod builds without making code changes.

  • Support turning React warnings into runtime exceptions. There are a few ways to do this:

  • Upgrade scala-js-dom to 2.0.0. This is mostly source-compatible with v1.2.0, but isn't binary-compatible. See the scala-js-dom v2 release notes.

Minor New Features

  • Add support for Monocle v3

  • Add Router DSL to handle repeated query params like ?a=1&a=2:

    • queryToSeq which gives you a Seq[(String, String)]
    • queryToMultimap which gives you a Map[String, Seq[String]
  • Add to object Callback:

    • def runAll(callbacks: CallbackTo[Any]*): Callback -- Any exceptions get a printStackTrace and are then discarded, and the next callback run.
  • Add to object CallbackTo:

    • def fromJsFn[A](f: js.Function0[A]): CallbackTo[A]
  • Add to Callback{,To} instances:

    • def reset: Callback -- If this completes successfully, discard the result. If any exception occurs, call printStackTrace and continue.
  • Add to AsyncCallback instances:

    • def reset: AsyncCallback[Unit] -- If this completes successfully, discard the result. If any exception occurs, call printStackTrace and continue.
  • Add to object CallbackOption:

    • def suspend[A](f: => CallbackOption[A]): CallbackOption[A]
    • def traverse_
    • def sequence_
  • Add to CallbackOption instances:

    • def finallyRun[B](runFinally: CallbackOption[B]): CallbackOption[A]
    • def when_(cond: => Boolean): CallbackOption[Unit]
    • def unless_(cond: => Boolean): CallbackOption[Unit]
  • New extension method showDom(): String available on mounted components given import japgolly.scalajs.react.test._ and/or import japgolly.scalajs.react.test.ReactTestUtil._

  • Add Reusable.emptyVdom which has the type Reusable[TagMod]

  • Add to cats module:

    • Implicit MonadThrow instances for scalajs-react effect types
    • Implicit Monoid instances for scalajs-react effect types with a monoidal value

Removals

  • Dropped support for Scala 2.12
  • Dropped support for Scala.JS 0.6.x
  • Dropped Scalaz support. The following modules are no longer available:
    • ext-monocle (deprecated version of ext-monocle-scalaz)
    • ext-monocle-scalaz
    • ext-scalaz72
  • Removed state monad support (ReactS, ReactST, etc)
  • Removed code deprecated in 1.5.x
  • Removed scala-collection-compat as a dependency
  • Removed CallbackKleisli
  • Removed .namespace from VDOM tags - it's an ancient legacy artifact that is no longer used

Changes: Backwards-Incompatible

  • scalajs-dom has been bumped to v2.0.0. This is backwards-incompatible with v1.x.y.

  • If you used to just add the extra module to your sbt's libraryDependencies and rely on core being included as a transitive dependency, it will no longer work. Explicitly add the core to your libraryDependencies.

  • In ReactTestUtils, act and actAsync now return the argument's value after it's executed

  • RouterCtl#onLinkClick now returns a Option[Callback] instead of a CallbackOption[Unit]. If necessary, wrap in CallbackOption.optionCallback to convert back to CallbackOption[Unit], or .getOrEmpty to turn into a Callback.

  • traverse and sequence methods in Callback, CallbackTo, AsyncCallback, CallbackOption now require an Iterable instead of an IterableOnce

  • Backwards-incompatible module changes:

    Old Module Name New Module Name
    ext-cats core-ext-cats
    ext-cats-effect core-ext-cats_effect
    ext-monocle Discontinued
    ext-monocle-cats extra-ext-monocle2
    ext-monocle-scalaz Discontinued
    ext-scalaz72 Discontinued
  • -Xelide-below no longer used. There are a few runtime checks that scalajs-react performs in a few places (currently js component wrapping, router construction). Previously you could disable and remove these from your JS output by specifying -Xelide-below ASSERTION as a scalac flag. Scala 3 doesn't support elision and it's too obscure a feature anyway so as of this version, scalajs-react runtime assertions will always appear in development mode (fastOptJS) and will be removed in production mode (fullOptJS).

  • Upgraded the Cats Effect to v3

  • The SVG attribute colorProfile is now colorProfileAttr

Changes: Backwards-Compatible

  • ReactTestUtils:

    • render methods now call act() under the hood
    • with*Render* methods that take a (f: M => A) can now also take
      • (f: (Element, M) => A)
      • withParent(f: Element => A)
  • Reusability derivation now also includes a reference-equality check by default. If the reference-equality check fails, then it falls back to a content-based check.

  • VdomNode instances now have a renderIntoDOM method (just like VdomElement)

  • Make covariant:

    • AsyncCallback
    • AsyncCallback.Forked
    • CallbackTo
    • CallbackOption
  • Additions

    • AsyncCallback.debounce(duration): AsyncCallback[Unit]
    • Callback.debounce(duration): Callback
    • ScalaFnComponent.withReuse{,By}
    • ScalaFnComponent.withChildrenAndReuse{,By}
    • Add a withFilter method to Callback(To) and AsyncCallback
    • Add a dispatch method to Callback and AsyncCallback which schedules (-and-forgets) the callback to be run in the background
    • TriStateCheckbox now accepts an optional Reusable[TagMod] in its Props that will be applied to the <input>
  • Bug fixes:

    • ScalaFnComponents now use VdomNodes instead of VdomElements
    • ForwardRefs now use VdomNodes instead of VdomElements
    • Input to AsyncCallback.traverse et al should only be evaluated once per callback invocation
    • Input to CallbackOption.traverse et al should only be evaluated once per callback invocation
  • Avoid boxing in React.Context and getSnapshotBeforeUpdate

  • ReactTestUtils is now a trait as well as an object so that you can mix it into your own test utils collection

  • Px[A]#extract now takes an implicit Px.Extract[A](Px[A] => A) argument instead of being a macro. If you're using this exotic feature, you can now provide your own Px.Extract typeclass instances.

  • Backwards-compatible dependency upgrades:

    • Cats to 2.6.1
    • Cats Effect to 3.2.9
    • Monocle (v2) to 2.1.0
    • Monocle (v3) to 3.1.0
    • Scala to 2.13.6
    • Scala.js to 1.7.1
    • Sourcecode to 0.2.7

Changes: Auto-Migratable

You can run the script in the Migration section at the bottom of the page to automatically perform these changes.

  • If you use any of the Router DSL .addCondition methods and provide a Page => CallbackTo[Boolean], you'll now need to add a By suffix (eg. addConditionBy).

  • Renamed

    • CatsReactReactCats
    • MonocleReactReactMonocle
    • In ReactTestUtils:
      • withNewBodyElementAsync{Callback ⇒ }
      • withNewDocumentElementAsync{Callback ⇒ }
      • withRenderedAsync{Callback ⇒ }
      • withRenderedIntoBodyAsync{Callback ⇒ }
      • withRenderedIntoDocumentAsync{Callback ⇒ }
  • Renamed (with old names still in place but deprecated)

    • AsyncCallback.{byName ⇒ suspend}
    • Callback.{byName ⇒ suspend}
    • CallbackTo.{byName ⇒ suspend}
    • CallbackOption.{liftOption ⇒ option}
    • CallbackOption.{liftOptionCallback ⇒ optionCallback}
    • CallbackOption.{liftOptionLike ⇒ maybe}
    • CallbackOption.{liftOptionLikeCallback ⇒ maybeCallback}
    • CallbackOption.{liftValue ⇒ delay}
    • CallbackOption.liftCallback(callback) ⇒ callback.toCBO
    • CallbackOption(callback) ⇒ callback.asCBO
    • JsFnComponent.fromScala.{byName ⇒ delay}
    • Reusability.{byName ⇒ suspend}
  • Renamed any and all vdom method names from `kebab-case` to camelCase

Migration

  1. Make sure to read the Changes: Backwards-Incompatible section above.

  2. Run this:

    find . -type f -name '*.scala' -exec perl -pi -e '
      s/\b(AsyncCallback[ .]+)byName\b/\1suspend/g;
      s/\b(Callback[ .]+)byName\b/\1suspend/g;
      s/\b(CallbackTo[ .]+)byName\b/\1suspend/g;
      s/\b(CallbackOption[ .]+)liftOption\b/\1option/g;
      s/\b(CallbackOption[ .]+)liftOptionCallback\b/\1optionCallback/g;
      s/\b(CallbackOption[ .]+)liftOptionLike\b/\1maybe/g;
      s/\b(CallbackOption[ .]+)liftOptionLikeCallback\b/\1maybeCallback/g;
      s/\b(CallbackOption[ .]+)liftValue\b/\1delay/g;
      s/\bCallbackOption *\( *([a-zA-Z_](?:[a-zA-Z0-9_. ]*[a-zA-Z0-9_])?) *\)/\1.asCBO/g;
      s/\bCallbackOption[ .]+liftCallback *\( *([a-zA-Z_](?:[a-zA-Z0-9_. ]*[a-zA-Z0-9_])?) *\)/\1.toCBO/g;
      s/\b(JsFnComponent[ .]+fromScala[ .]+)byName\b/\1delay/g;
      s/\b(Reusability[ .]+)byName\b/\1suspend/g;
      s/\bMonocleReact\b/ReactMonocle/g;
      s/\bCatsReact\b/ReactCats/g;
      s/\b(withNewBodyElementAsync)Callback\b/\1/g;
      s/\b(withNewDocumentElementAsync)Callback\b/\1/g;
      s/\b(withRenderedAsync)Callback\b/\1/g;
      s/\b(withRenderedIntoBodyAsync)Callback\b/\1/g;
      s/\b(withRenderedIntoDocumentAsync)Callback\b/\1/g;
      s/\bnew OnUnmount.Backend\b/OnUnmount()/g;
      s/\b(addCondition(?:With(?:Optional)?Fallback)?)( *\( *[a-zA-Z_][a-zA-Z0-9_]* +=>)/\1By\2/g;
      s/Reusability\.byRef +\|\| +(Reusability\.(?:derive|caseClassExcept))/\1/g;
      s/`all-scroll`/allScroll/g;
      s/`bidi-override`/bidiOverride/g;
      s/`border-box`/borderBox/g;
      s/`break-all`/breakAll/g;
      s/`break-word`/breakWord/g;
      s/`cjk-decimal`/cjkDecimal/g;
      s/`col-resize`/colResize/g;
      s/`color-profile`/colorProfile/g;
      s/`content-box`/contentBox/g;
      s/`context-menu`/contextMenu/g;
      s/`decimal-leading-zero`/decimalLeadingZero/g;
      s/`e-resize`/eResize/g;
      s/`ew-resize`/ewResize/g;
      s/`font-face-format`/fontFaceFormat/g;
      s/`font-face-name`/fontFaceName/g;
      s/`font-face-src`/fontFaceSrc/g;
      s/`font-face-uri`/fontFaceUri/g;
      s/`font-face`/fontFace/g;
      s/`hiragana-iroha`/hiraganaIroha/g;
      s/`inline-block`/inlineBlock/g;
      s/`inline-flex`/inlineFlex/g;
      s/`inline-table`/inlineTable/g;
      s/`katakana-iroha`/katakanaIroha/g;
      s/`keep-all`/keepAll/g;
      s/`line-through`/lineThrough/g;
      s/`list-item`/listItem/g;
      s/`lower-alpha`/lowerAlpha/g;
      s/`lower-greek`/lowerGreek/g;
      s/`lower-latin`/lowerLatin/g;
      s/`lower-roman`/lowerRoman/g;
      s/`missing-glyph`/missingGlyph/g;
      s/`n-resize`/nResize/g;
      s/`ne-resize`/neResize/g;
      s/`nesw-resize`/neswResize/g;
      s/`no-drop`/noDrop/g;
      s/`not-allowed`/notAllowed/g;
      s/`ns-resize`/nsResize/g;
      s/`nw-resize`/nwResize/g;
      s/`nwse-resize`/nwseResize/g;
      s/`padding-box`/paddingBox/g;
      s/`pre-line`/preLine/g;
      s/`pre-wrap`/preWrap/g;
      s/`preserve-3d`/preserve3d/g;
      s/`row-resize`/rowResize/g;
      s/`s-resize`/sResize/g;
      s/`se-resize`/seResize/g;
      s/`sw-resize`/swResize/g;
      s/`table-caption`/tableCaption/g;
      s/`table-cell`/tableCell/g;
      s/`table-column-group`/tableColumnGroup/g;
      s/`table-column`/tableColumn/g;
      s/`table-footer-group`/tableFooterGroup/g;
      s/`table-header-group`/tableHeaderGroup/g;
      s/`table-row-group`/tableRowGroup/g;
      s/`table-row`/tableRow/g;
      s/`text-bottom`/textBottom/g;
      s/`text-top`/textTop/g;
      s/`under left`/underLeft/g;
      s/`under right`/underRight/g;
      s/`upper-alpha`/upperAlpha/g;
      s/`upper-latin`/upperLatin/g;
      s/`upper-roman`/upperRoman/g;
      s/`vertical-text`/verticalText/g;
      s/`w-resize`/wResize/g;
      s/`x-large`/xLarge/g;
      s/`x-small`/xSmall/g;
      s/`xx-large`/xxLarge/g;
      s/`xx-small`/xxSmall/g;
      s/`zoom-in`/zoomIn/g;
      s/`zoom-out`/zoomOut/g;
    ' {} +

Changes in RCs

If you're interested in the changes between each RC release, see here.

Thanks

A lot of this was kindly sponsored by Gemini/NOIRLab/AURA. Huge thanks to @cquiroz for making this possible, and to @rpiaggio for the awesome ideas that helped guide design.

We all want features like Scala 3 support but in reality it's a ton of work to implement. It's not very feasible for an OSS maintainer to do literally months of full-time work for free. On behalf of myself and the scalajs-react community, thank you so much for sponsoring this huge effort!