- Compile-Time Settings
- Runtime Settings (development-mode only)
There's currently a limitation that components use the compile-time settings available when they're compiled. Seems like a pretty obvious way to go so why is it a limitation? When you're writing components in your app (which is what the vast majority of us do), then this isn't a limitation and it will work the way you expect. On the other hand, if you're writing components in a library, the library author's settings are used, and downstream users (currently) don't have a way to recompile it with their own settings. This may (and should) change in the future. If this is important to you or your organisation, feel free to reach out and sponsor the required work.
First add this to your sbt:
scalacOptions ++= // Required since sbt 1.6.0
sys.props.iterator
.filter(_._1.contains("japgolly"))
.map(x => s"-D${x._1}=${x._2}")
.toSeqCurrently, you have to specify compile-time settings to sbt directly when you start it.
Examples:
# Format:
sbt \
-D<key1>=<value1> \
-D<key2>=<value2> \
...
# Use defaults
sbt
# Clear out all component names
sbt -Djapgolly.scalajs.react.component.names.all=blankSpecifies the transformation to apply to all component display-names, whether automatically/implicitly specified, or explicitly specified when you create the component.
sbt -Djapgolly.scalajs.react.component.names.all=allow|blank
| Setting | Outcome |
|---|---|
allow (default) |
Allow all component names. Doesn't perform any transforms. |
blank |
Clear all component names. Transforms all names into "". |
Determines how implicitly name components that haven't been created with the explicit specification of an display-name.
sbt -Djapgolly.scalajs.react.component.names.implicit=full|short|blank
| Setting | Outcome |
|---|---|
full (default) |
FQCN + field name (except with a trailing .Comp or .Component removed) |
short |
The last component of the full name (above) |
blank |
Empty string. No automatic/implicit component names. |
Given the following components:
package com.example
import japgolly.scalajs.react._
object UsersEditor {
val Component = ScalaComponent.builder[Unit].renderStatic(<.div).build
}
object Layout {
val Header = ScalaComponent.builder[Unit].renderStatic(<.div).build
val Footer = ScalaComponent.builder[Unit].renderStatic(<.div).build
}Outcomes:
| Setting | Name | Name | Name |
|---|---|---|---|
full (default) |
com.example.UsersEditor |
com.example.Layout.Header |
com.example.Layout.Footer |
short |
UsersEditor |
Header |
Footer |
blank |
Instructs scalajs-react to use a custom instance of ScalaJsReactConfig that you've provided.
Configure as follows where fqcn is the fully-qualified classname of your config object.
sbt -Djapgolly.scalajs.react.config.class=<fqcn>
And then create your object in one of the following ways:
// Recommended method
object Example1 extends ScalaJsReactConfig.Defaults {
// override settings as desired
}
// Paranoid/full-power method
object Example2 extends ScalaJsReactConfig {
// `transparent inline` below so that transformations are performed at compile-time
// and only the results appear in the output JS.
override transparent inline def automaticComponentName(name: String) =
??? // your impl here
override transparent inline def modifyComponentName(name: String) =
??? // your impl here
override val reusabilityOverride =
??? // your impl here
}sbt -Djapgolly.scalajs.react.config.class=com.example.CustomConfig
package com.example
import japgolly.scalajs.react._
object CustomConfig extends ScalaJsReactConfig.Defaults {
// `transparent inline` so that the transformation is performed at compile-time
// and only the result appears in the output JS.
override transparent inline def automaticComponentName(name: String) =
name + " (auto)"
}Runtime settings are designed for use in development-mode only (fastOptJS).
They are omitted from production-mode output (fullOptJS).
Runtime settings must
- be specified in your app's
mainmethod or equivalent entrypoint - be evaluated before any affected components are created
Example:
import japgolly.scalajs.react._
import org.scalajs.dom
import scala.scalajs.js.annotation._
object Main {
@JSExportTopLevel("main")
def main() = {
// Apply runtime settings before any components are referenced
Reusability.disableGloballyInDev()
// Start app
val container = dom.document.getElementById("root")
val root = ReactDOMClient.createRoot(container)
root.render(MyApp())
}
}Note: Runtime settings only affect development-mode (fastOptJS) and must be applied before any components are created.
This globally disables Reusability.shouldComponentUpdate so that it doesn't nothing.
[ReusabilityOverlay has been deprecated in v3 with no replacement — use React's Profiler instead]
Note: Runtime settings only affect development-mode (fastOptJS) and must be applied before any components are created.
This makes calls to Reusability.shouldComponentUpdate also display a little UI overlay for you to inspect/debug
component updates. You can see a live example of this in use here.
Note: Runtime settings only affect development-mode (fastOptJS) and must be applied before any components are created.
You can modify the behaviour of Reusability.shouldComponentUpdate to apply any custom logic you like
by creating your own instance of ScalaJsReactConfig.ReusabilityOverride and providing to
ScalaJsReactConfig.Defaults.overrideReusabilityInDev().
Example:
import japgolly.scalajs.react._
import org.scalajs.dom
import scala.scalajs.js.annotation._
object Main {
private object logComponents extends ScalaJsReactConfig.ReusabilityOverride {
override def apply[P: Reusability, C <: Children, S: Reusability, B, U <: UpdateSnapshot] = b => {
println("Detected component with Reusability.shouldComponentUpdate: " + b.name)
b
}
}
@JSExportTopLevel("main")
def main() = {
// Apply runtime settings before any components are referenced
ScalaJsReactConfig.Defaults.overrideReusabilityInDev(logComponents)
// Start app
val container = dom.document.getElementById("root")
val root = ReactDOMClient.createRoot(container)
root.render(MyApp())
}
}