Skip to content

Latest commit

 

History

History
138 lines (111 loc) · 5.52 KB

1.3.0.md

File metadata and controls

138 lines (111 loc) · 5.52 KB

1.3.0

  • The .getDOMNode callback can sometimes execute when unmounted which is an increasingly annoying bug to track down. Since React 16 with its new burn-it-all-down error handling approach, an occurance of this can be fatal (and caused my entire app to just suddenly unmount in disappear in the middle of a demo).
    This release adjusts the types to restore compile-time safety. Unfortunately it's a breaking change. There is now a proper ADT:

                                   ComponentDom
                                    ↑        ↑
                 ComponentDom.Mounted        ComponentDom.Unmounted
                    ↑            ↑
    ComponentDom.Element      ComponentDom.Text
    

    Calling .getDOMNode from without lifecycle callbacks, returns a ComponentDom.Mounted, logically equivalent to before. Calling .getDOMNode on a mounted component instance or a BackendScope now returns ComponentDom which may or may not be mounted. Jump into the ComponentDom source to see the available methods but in most cases you'll use one of the following:

    trait ComponentDom {
      def mounted  : Option[ComponentDom.Mounted]
      def toElement: Option[dom.Element]
      def toText   : Option[dom.Text]

    In unit tests you'll typically use asMounted().asElement() or asMounted().asText() for inspection.

  • React 16.3 support

    • New component lifecycle: getDerivedStateFromProps
    • New component lifecycle: getSnapshotBeforeUpdate
      There is compile-time enforcement of some rules around getSnapshotBeforeUpdate which you'll find out about at compile-time (in an informative way) if you violate; you can also read about it and how it was implemented here: https://japgolly.blogspot.com/2018/07/enforcing-rules-at-compile-time-example.html
    • React Context API implemented via React.createContext and React.Context.
    • React ref forwarding
      • Forward a ref via React.forwardRef
      • Wrap a JS ref-forwarding component via JsForwardRefComponent
      • Refs are now based on React.createRef()
      • Components now have .withRef functions just like VDOM
      • docs & example
    • Add React.StrictMode
  • React 16.4 support

    • Add new types:
      • ReactPointerEvent
      • ReactPointerEventFrom[N]
      • ReactPointerEventFromHtml
      • ReactPointerEventFromInput
      • ReactPointerEventFromTextArea
    • Add new events to the vdom and for tests, event simulation:
      • onGotPointerCapture
      • onLostPointerCapture
      • onPointerCancel
      • onPointerDown
      • onPointerEnter
      • onPointerLeave
      • onPointerMove
      • onPointerOut
      • onPointerOver
      • onPointerUp
  • React 16.5 support

    • New event: onAuxClick
    • New mouse event attributes: movementX and movementY
    • New pointer event attributes: tangentialPressure and twist
  • Adding support for React 16.3's new getSnapshotBeforeUpdate lifecycle callback was quite disruptive and resulted in the following knock-on changes:

    • .configure in ScalaComponent.builder now only accepts one argument.

    • ScalaComponent.Config (used for externalising and reusing opaque component lifecycle logic) has changed from a bearable type Config[P, C <: Children, S, B] to the horrendous definition below. It's not something that many people use and even when they do it's infrequent, but hopefully a workaround can be found soon anyway.

      /** This is terrible and repulsive but Scala doesn't allow anything less repulsive.
        * We'll keep this correctly modelling the reality for now and soon see if maybe we can use macros to
        * simplify it's creation (and avoid the need to use this explicitly).
        */
      type Config[P, C <: Children, S, B, US <: UpdateSnapshot, US2 <: UpdateSnapshot]
    • LogLifecycle has been deleted without replacement

  • Added to ScalaComponent.builder: .configureWhen and .configureUnless

  • Deprecated ReactFragment and replaced with React.Fragment

  • Add setRequestHeader to Ajax

  • Trying to treat a JS Symbol as a React component now provides a meaningful error message

  • Add cloneElement(…) to React JS facade

  • Add to japgolly.scalajs.react.test.SimEvent.{Mouse,Pointer}

    • def simulateClick and def simulationClick
    • def simulateContextMenu and def simulationContextMenu
    • def simulateDoubleClick and def simulationDoubleClick
  • New HTML attributes

    • noModule
    • playsInline
  • New SVG attribute: focusable

  • ScalaFnComponents that have a Props type of Unit are now invoked as Blah() instead of Blah(())

  • DeprecateasEventDefault in the object CallbackOption and move it to the class CallbackOption

  • Add asEventDefault to Callback(To)

  • Update dependencies:

    • Cats to 1.4.0
    • Scalaz to 7.2.26
    • Scala.JS to 0.6.25

Migration

find . -name '*.scala' -type f -exec perl -pi -e '
  s/ReactFragment/React.Fragment/g;
  ' {} +

find . -path '*/test/scala/*.scala' -type f -exec perl -pi -e '
  s/getDOMNode.asElement/getDOMNode.asMounted().asElement()/g;
  s/getDOMNode.asText/getDOMNode.asMounted().asText()/g;
  s/getDOMNode.domCast/getDOMNode.asMounted().domCast/g;
  ' {} +

Support

If you like what I do —my OSS libraries, my contributions to other OSS libs, my programming blog— and you'd like to support me, more content, more lib maintenance, please become a patron! I do all my OSS work unpaid so showing your support will make a big difference.