Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 08:10
    armanbilge commented #511
  • 08:09
    armanbilge edited #511
  • 08:08
    armanbilge synchronize #511
  • Oct 20 00:15
    armanbilge synchronize #511
  • Oct 18 19:45
    shadaj demilestoned #233
  • Oct 18 19:37
    shadaj commented #494
  • Oct 17 23:14
    armanbilge opened #511
  • Oct 14 13:17
    oleg-py synchronize #494
  • Oct 14 12:39
    oleg-py synchronize #494
  • Oct 13 05:25
    shadaj commented #494
  • Oct 11 08:31
    oleg-py synchronize #494
  • Oct 11 08:20
    oleg-py synchronize #494
  • Oct 11 07:34
    oleg-py synchronize #494
  • Oct 11 07:23
    oleg-py synchronize #494
  • Oct 09 19:58
    shadaj commented #494
  • Oct 06 20:04
    scala-steward commented #497
  • Oct 06 20:04
    scala-steward closed #497
  • Oct 06 20:04
    scala-steward opened #510
  • Sep 16 23:01
    scala-steward closed #500
  • Sep 16 23:01
    scala-steward commented #500
asaadza
@asaadza

What's a reasonable/idiomatic way to do this given

  def useClientRect(initial: ClientRect) = {
    val (rect, setRect) = Hooks.useState[ClientRect](initial)
    val ref = Hooks.useCallback[Element => ()](node => {
      if (node != null) {
        setRect(node.getBoundingClientRect())
      }
    }, List())
    (rect, ref)
  }

?

asaadza
@asaadza

hopefully, this is not the best answer

  val component = FunctionalComponent[Unit] { _ => 
    val (rect, cb) = Draw.useClientRect(null) 
    val ref1 = Hooks.useRef[dom.html.Element](null)
    Hooks.useEffect({ () => cb(ref1.current) })
    div(
      h1(ref := ref1)("Tall Writings"),
      {
        if(rect != null)  
          h2(s"How tall?! ${rect.height}")
        else
          h2("nope")
      }
    )
  }

especially since it gives Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.

asaadza
@asaadza
Even if adding a constraint/"dependency array" on useEffect enables it to run, is it possible to reason about the order of side-effects (setting the ref and calculating the bounding rectangle) and, rendering in such an impl?
Shadaj Laddad
@shadaj
@asaadza well what's happening is that the effect runs, which changes the state of your rect, which causes the effect to run again, and so on. You probably need to use useLayoutEffect with an empty dependency array so that the ref1 will be available but the effect will only run once
asaadza
@asaadza
@shadaj that's worth a try too, thanks, or one could just get a ref to the underlying dom.html.Element and use the client properties on it in some side-effecty hook (which might turn out to be the one you suggest anyway, to make sure everything is already where it is meant to be!). I was really more wondering whether slinky will support setting the ref attribute to a callback at some point, since it seems to make the non-determinism argument moot in such cases, or do you consider that to be an anti-pattern in this context.
PS that live example/hackery I linked to in my initial post is actually based on the react hooks FAQ, :) , and it did look like interesting "sugar" for that sort of use case, even though it's a shame we have to resort to such measures at all.
Shadaj Laddad
@shadaj
@asaadza Slinky already does support callback refs! You can use them on both tag elements and components. Are you unable to pass in a callback to ref := for some reason?
asaadza
@asaadza
yes :)
asaadza
@asaadza
overloaded method := with alternatives: [T <: slinky.core.TagElement, E <: T#RefType](v: slinky.core.RefAttr[E]): slinky.core.AttrPair[T] <and> [T <: slinky.core.TagElement](v: T#RefType => Unit): slinky.core.AttrPair[T] cannot be applied to (() => Unit)
asaadza
@asaadza
Changing the domain of the callback (eg to some sort of scalajs-dom or slinky-dom element) does not seem to fix it either.
Is there some alternative to scalafiddle these days? Hopefully scala-center will take that over at some point because it was a great resource, for all sorts of reasons, while the available libs and scala/sjs versions were kept close to uptodate, and even though scastie is also really good too, it wouldn't probably help us here.
asaadza
@asaadza

@shadaj - is this the intended usage?

div(
  ref :=[div.tagType] { el =>
    if (el != null) {
      val rect = el.getBoundingClientRect()
      println(rect.top)
    }
  }
),

That works anyway (not sure why inference was failing, but with the explicit type param it's OK).
Nice job for including even that in Slinky! Have you, or anybody, actually used it anywhere?

Domantas Petrauskas
@ptrdom
Does @react macro work for anyone on IntelliJ 2020.3.1? Can't figure out how to make it work.
1 reply
peterstorm
@peterstorm:matrix.org
[m]
How do I best fetch data in a useEffect before rendering a the component? I tried the whole if (isLoading) { h1(“loading”) } else { render the stuff.... } but it didn’t seem to work
And I set the state in a useStare hook in the useEffect hook
peterstorm
@peterstorm:matrix.org
[m]
Ah, got it to work
Alexis Hernandez
@AlexITC
@peterstorm:matrix.org I built something reusable for that
Shadaj Laddad
@shadaj
@asaadza yep that's the API to use, but it's odd that you had to include the explicit type parameter (there's a test at https://github.com/shadaj/slinky/blob/master/tests/src/test/scala/slinky/core/TagTest.scala#L86 where functional refs are compiling without explicit type params, I wonder what's the difference)
peterstorm
@peterstorm:matrix.org
[m]
How in the world do I make a direct link work in Slinky? Or maybe just React in general? If I go to a link I have defined in a router, I get 404 when I visit it.
I have to navigate to the root page, and then press a link
Øyvind Raddum Berg
@oyvindberg
you typically need server side support for the history api to work
peterstorm
@peterstorm:matrix.org
[m]
Ah, shugs :D
peterstorm
@peterstorm:matrix.org
[m]
Does slinky support ssr in any way?
shadaj
@shadaj:matrix.org
[m]
peterstorm: yes! the Slinky home page is SSR-ed to a static site, take a look at https://github.com/shadaj/slinky/blob/master/docs/src/main/scala/slinky/docs/Main.scala#L94 for an example
mn98
@mn98

Hi all. I'm sure I'm missing something obvious here. What's the Slinky equivalent of creating an array of Refs? I'm using functional components with hooks.
In vanilla React we have:

const ref = useRef();
const refsArray = useRef([]);

In Slinky we have:

val ref = useRef[T](null)
val refsArray = ???

I'm struggling to fill in the question marks. As you can tell, I'm trying to create a dynamic collection of Refs. Any hints or examples greatly appreciated!

In vanilla React this example makes it look incredibly easy. I'm hoping it is as trivial in Slinky!
shadaj
@shadaj:matrix.org
[m]
@mn98: so in React, there's actually no such thing as an array of Refs. In the JavaScript example you gave, what you actually end up with is a Ref containing an array. So in Slinky, the equivalent code would be useRef(Array(...))
mn98
@mn98
@shadaj:matrix.org right, I clearly need educating here! So, what's the Slinky way to create a dynamic sequence of Refs? In my case I have a dynamically growing collection of charts (using chart js via ScalablyTyped) for which I need a dynamically growing collection of Canvas Refs. It's proving much trickier than I first envisaged.
mn98
@mn98
Even any hints as to how someone might approach this would be great.
shadaj
@shadaj:matrix.org
[m]
@mn98: the way to go would probably be to still create one ref, but store a mutable collection inside that you can update. In general, with React hooks you can't be dynamic since React expects the same number of hooks to be used in every render of the component
mn98
@mn98
My current thinking is to abandon this "dynamic refs" thing and use functional components to solve the issue. I could have a dynamically growing collection of components modelled as state in the "parent" component, and then this collection gets re-rendered as it grows. Each "child" component can take the necessary props and deal with its own chart and canvas.
If anyone has better ideas please do let me know! I'm getting a lot done with Slinky, but I've never written a line of JS in my life so I've plenty to learn.
shadaj
@shadaj:matrix.org
[m]
@mn98: that sounds like a good plan! generally, the more state you can push into child components, the better
peterstorm
@peterstorm:matrix.org
[m]
When I deploy a Slinky app, can I do the same thing with the "proxy" setting in a package.json file, and just have relative urls in the Slinky api component?
Or do I not need that
peterstorm
@peterstorm:matrix.org
[m]
Ah, seems I don't need it
shadaj
@shadaj:matrix.org
[m]
Over the past two weeks, I've been working on extracting the Slinky IntelliJ support as a standalone plugin, and it's now available in the JetBrains Marketplace (https://plugins.jetbrains.com/plugin/15748-slinky-library-support/versions/develop/107890)! Please test it out so we can iron out any bugs before the next release (which will push the plugin into the stable channel and make it searchable).
asaadza
@asaadza
@shadaj:matrix.org - nice job: at a quick look, big reduction in false negatives/squiggles and navigation works too. Thank you! In fact, the only difference I noticed vs the previous version I had is that IJ now requires a restart after installing the plugin, as with most plugins (probably because it is now more packaged, in a folder) .
I will also get back at some point re your comment about the type-inference wrt call back refs, thanks.
mcallisto
@mcallisto
@shadaj:matrix.org works for me, awesome!
Domantas Petrauskas
@ptrdom
I tried out how hot reloading works with example project and it seems to not preserve state for functional components between reloads. Is it not supposed to work with them or is it a bug?
Alexis Hernandez
@AlexITC
I think that's documented, and its the expected behavior
shadaj
@shadaj:matrix.org
[m]
@dope9967: yeah, as @AlexITC said Slinky doesn't have support for hot reloading functional components yet since we need to implement support for the React Refresh runtime
Domantas Petrauskas
@ptrdom
oh, I've read the docs through and through but somehow didn't notice it, all good, thanks for prompt replies!
nkgm
@nkgm
@react class Tab extends StatelessComponent {
  case class Props(title: String)
  ...
}

@react class TabList extends StatelessComponent {
  case class Props(tab1: Tab)
  ...
}

// doesn't work
TabList(TabList.Props(
  Tab(Tab.Props("tab 1"))
))
Instantiating a Tab the usual way returns an instance of KeyAndRefAddingStage[Tab], which won't typecheck for the tab1: Tab prop. I am aware this isn't the usual way of doing things, but is it possible?
vonchav
@voonchav_gitlab
Hi, wondering if there will be a new release of slinky coming out soon, with support of the new plugin as well as scalajs 1.4.x :)
shadaj
@shadaj:matrix.org
[m]
@nkgm: you won't be able to typecheck it as a Tab because it's no longer an instance of the Tab type; when using components you end up with a React type instead, represented by the ReactElement type
if you need access to the underlying Tab, however, you can use a ref! Slinky will automatically typecheck the ref to the component type
@voonchav_gitlab: likely this week :) Scala.js 1.4.x might not make it till a later release depending on how easy it is to integrate bundle splitting support
vonchav
@voonchav_gitlab
oh, bundle splitting support, sweet.
nkgm
@nkgm
Thanks @shadaj:matrix.org . Not sure how to use refs to rewrite the above scenario. Could you give me an example?
shadaj
@shadaj:matrix.org
[m]
@nkgm: take a look at https://slinky.dev/docs/refs/. Basically, you can only get access to the class instance once the component has been rendered inside some parent.
nkgm
@nkgm

Only way I can think of is this (fails with tab1__Lslinky_core_facade_ReactRef().current is null)

object tabsWithRefs {

  @react class Tab extends StatelessComponent {
    case class Props(title: String)

    def render() = props.title
  }

  @react class TabList extends StatelessComponent {
    case class Props(tab1: ReactRef[Tab])

    def render() = props.tab1.current.render()
  }
}
...

import tabsWithRefs._
val tabRef = React.createRef[Tab.Def]
Tab("tab title").withRef(tabRef)
TabList(tabRef)

BTW, for the time being I'm using KeyAndRefAddingStage[Tab]-like props for typechecking child components.

shadaj
@shadaj:matrix.org
[m]
@nkgm: you shouldn't ever need to call .render on a component, instead your def render in TabList should be implemented as just returning a Tab(...); that way, you don't even need a ref, which is usually only needed for imperative actions