Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New crystal with contexts. #690

Merged
merged 2 commits into from
Apr 5, 2021
Merged

New crystal with contexts. #690

merged 2 commits into from
Apr 5, 2021

Conversation

rpiaggio
Copy link
Contributor

@rpiaggio rpiaggio commented Apr 3, 2021

Crystal now uses React's context for storing, well, context. It provides a component to store context (ContextProvider) and a mechanism where consumers can use just the value of a context, or get a View which allows modifying said context. Also, it supports multiple contexts.

This PR includes a little demo on how to use it which is not meant to go into production. After we have implemented a proper help system, we can remove this:

Kapture 2021-04-03 at 12 00 41

One disadvantage of this approach is that we can't access contexts from lifecycle methods. Although React provides a way to do this, support in scalajs-react is pending (japgolly/scalajs-react#890). To work around this temporarily, context is passed implicitly in props from parents to child components who need it in lifecycle methods.

The old AppRoot has been renamed to StateProvider.

AppCtx.runWithCtx { implicit appCtx =>
val ConstraintSetObsLiveQuery =
ScalaFnComponent[View[ConstraintSetsWithObs] => VdomNode](render =>
AppCtx.using { implicit appCtx =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it so that we execute this on IO when calling using? Or is it different than runWitCtx in that sense

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inner workings are different than before. Ctx.using (or Ctx.usingView) return a VdomElement, so they can only be used within render. In other words, they act as a component; and since it's declarative, a name with run in it didn't seem fitting anymore. Also, the function passed to them must be a render function, returning a VdomNode.

This is a functionality provided by React, and is basically a way of "teleporting" props further down the component tree, without the need of explicitly passing them in all intermediate components. If the context changes, it is automatically propagated to all .using(View) blocks in the currently rendered component tree.

"Explore"
"Explore",
HelpCtx.usingView { help =>
val helpMsg = help.zoom(HelpContext.msg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this will be useful

Copy link
Contributor

@cquiroz cquiroz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot, this was a lot of work but will be useful in a few important scenarios

Copy link
Contributor

@toddburnside toddburnside left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rpiaggio rpiaggio merged commit 1af9077 into master Apr 5, 2021
@rpiaggio rpiaggio deleted the crystaler branch April 5, 2021 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants