solid icon indicating copy to clipboard operation
solid copied to clipboard

Add Conditional refs

Open vxncetxn opened this issue 3 years ago • 7 comments

Describe the bug

Conditional refs within a <For> block do not work as expected:

<For each={[1, 2]}>
      {(num: number) => (
        <div
          ref={num === 1 ? oneRef : twoRef}
          onClick={() =>
            num === 1 ? console.log(oneRef) : console.log(twoRef)
          }
        >
          number: {num}
        </div>
      )}
</For>

In the above snippet, the refs do not actually get applied to the either element.

Your Example Website or App

https://playground.solidjs.com/?hash=-912917438&version=1.4.3

Steps to Reproduce the Bug or Issue

  1. This issue can be better observed in this playground example one.
  2. Observe that logging either refs to console (from both createEffect and onClick) return undefined.
  3. Observe also that the work-around (which is to forgo the use of the <For> block) which is commented out in the above example returns the expected behaviour (logs the refs to console correctly).
  4. What also works is non-conditional usage of refs as seen in playground example two.
  5. In this case, the ref will be passed to the second element only and returns it when logged to console.

Expected behavior

As a user, I expected refs to be passed to both elements conditionally (as confirmed by logging it to console) but neither elements received the refs (as seen when logging the refs to console returns undefined)

Screenshots or Videos

No response

Platform

  • OS: macOS
  • Browser: Chrome, Firefox, Safari
  • Version: Chrome v104, Firefox v104, Safari v15.0

Additional context

No response

vxncetxn avatar Aug 25 '22 12:08 vxncetxn

Hmm.. interesting. This has nothing to do with <For> We've never supported conditional refs. Didn't really think of them as a thing because they never update but I suppose structurally that could be a case. Not a bad feature request.

ryansolid avatar Aug 25 '22 17:08 ryansolid

You can still use member access refs[cond ? 'prop1' : 'prop2'] instead plain variable to mimic conditional refs.

mdynnl avatar Aug 25 '22 18:08 mdynnl

@mdynnl You mean putting the refs into an object or array and conditionally accessing them right? I just tried that and I don't think it works. Regular non-conditional access (refs.prop1) doesn't work as well.

vxncetxn avatar Aug 25 '22 18:08 vxncetxn

https://playground.solidjs.com/?hash=1968952564&version=1.4.3 same should work for array

mdynnl avatar Aug 25 '22 18:08 mdynnl

@mdynnl Indeed that works, thanks a lot!

vxncetxn avatar Aug 25 '22 19:08 vxncetxn

@vxncetxn It works if you specify ref as a function:

ref={(el) => (num === 1 ? (oneRef = el) : (twoRef = el))}

https://playground.solidjs.com/?hash=1401208615&version=1.4.3

sigerello avatar Aug 27 '22 17:08 sigerello

If you don't need the reactivity of the For component, would it be bad style to do const divs = [1, 2].map((i) => <div/>), then do whatever you plan to do with the refs directly on divs (if you only need onClick, I think you could work with e.target as well) and then return divs?

fweth avatar Sep 04 '22 17:09 fweth

This requires more discussion/design. Welcome anyone to do so over in discussions.

ryansolid avatar Oct 20 '22 06:10 ryansolid